1
votes

I'm trying to solve a problem with a custom control ported from a VCL C++ application. The idea is that individual parts of the control are drawn first on a new Graphics object and then merged with the Graphics object from the control's paint method.

I've created a simplified example:

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

namespace Test
{
    public class Form1 : Form
    {
        private PictureBox pictureBox;

        public Form1()
        {
            pictureBox = new PictureBox();
            pictureBox.Dock = DockStyle.Fill;
            pictureBox.Paint += new PaintEventHandler(pictureBox_Paint);

            ClientSize = new Size(100, 50);
            Controls.Add(pictureBox);
        }

        private void pictureBox_Paint(object sender, PaintEventArgs e)
        {
            SolidBrush blackBrush = new SolidBrush(Color.Black);

            Bitmap bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
            Graphics graphics = Graphics.FromImage(bitmap);

            Font font = new Font(pictureBox.Font, FontStyle.Regular);
            graphics.DrawString("simple test", font, Brushes.Black, 0, 0);

            e.Graphics.DrawImage(bitmap, 0, 0);
        }
    }
}

Running the above code results in the text being drawn too thick:

When i modify the code to draw the text directly to the Graphics object of the PictureBox i get the correct result:

This problem only occurs with text rendering. Lines and other shapes are rendered correctly. Any ideas how to solve this?

Thanks in advance.

1

1 Answers

1
votes

This happens because you forgot to initialize the bitmap pixels. By default they are Color.Transparent, which is black with an alpha of 0. This goes wrong when you draw anti-aliased text into the bitmap, the aliasing algorithm will draw pixels that blend from the foreground (black) to the background (also black). Blobby letters that are not anti-aliased is the result.

This is not a problem in the 2nd screenshot because the background pixels were drawn to battleship gray by the default Form.OnPaintBackground() method. Simply add the Graphics.Clear() method to fix your problem:

using (var bitmap = new Bitmap(pictureBox.Width, pictureBox.Height)) {
    using (var graphics = Graphics.FromImage(bitmap)) {
        graphics.Clear(this.BackColor);                // <== NOTE: added
        graphics.DrawString("simple test", pictureBox1.Font, Brushes.Black, 0, 0);
    }
    e.Graphics.DrawImage(bitmap, 0, 0);
}

With using statements added to prevent your program from crashing when the garbage collector doesn't run often enough.