Good day! I am writing my own graphic editor. Now I am at the stage of developing a text tool. I use TextBox control to write text. And I ran into the following problem: when I redraw text from a textbox to a bitmap , it shifts a bit depending on the font. Here is the part of the code:

 var g = Graphics.FromImage(bitmap); g.DrawString(textBox.Text, textBox.Font, new SolidBrush(textBox.ForeColor), textBox.Location); 

Can you tell me how to solve this problem? So that the text is drawn in the same place where it was in the textBox . I also tried to use a label and draw it on a bitmap , but the problem does not go away. All the same, a little, yes shifted.

I tried through Textrender.DrawText, but the text is still shifted. I will give an example for Label. I did everything in the PictureBox.OnPaint(object sender, PaintEventArgs e) method PictureBox.OnPaint(object sender, PaintEventArgs e) . Below are two pieces of code:

one)

 label.Visible = false; TextRenderer.DrawText(e.Graphics, label.Text, label.Font, label.Location, label.ForeColor); 

2)

 label.Visible = false; var bitmap = new Bitmap(pictureBox.Width, pictureBox.Height); var g = Graphics.FromImage(bitmap); TextRenderer.DrawText(g, label.Text, label.Font, label.Location, label.ForeColor); e.Graphics.DrawImage(bitmap, 0, 0); 

Those. in the first case I draw on the pictureBox itself, in the second - on a bitmap, which I then draw on the pictureBox.

I can notice that the line:

 label.UseCompatibleTextRendering = true; 

you can not write, because that assign true, that false - the result is the same in my case (although it is not clear why)

label.Visible = false; - wrote to ensure that it does not appear on the pictureBox when we have already drawn the text.

Below I put three pictures:

1 - initially looks like a label on the pictureBox,

2 - as when drawing on the pictureBox,

3 - as when drawing on bitmap.

They clearly show that the text is moving. Moreover, in the case of bitmap, the font also became bold for some reason.

label, pictureBox, bitmap

  • one
    check textbox indents - Grundy
  • How? + The text is drawn not only slightly to the right or left, but also higher / lower - Valeriy
  • in the textbox settings - Grundy
  • Try to use TextRenderer.DrawText - Alexander Petrov
  • If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky

1 answer 1

In the first versions of dotnet, GDI + technology, the Graphics.DrawString method, was used to draw text. Then, from the version of .NET 2.0, text rendering was transferred to GDI - the TextRenderer.DrawText method in order to improve quality and performance.

The default setting for the entire project is set in the Program.cs file. There should be a string

 Application.SetCompatibleTextRenderingDefault(false); 

The parameter false means using GDI. link

Some controls, in particular, Label , have the UseCompatibleTextRendering property, which allows you to specify the rendering method used.

TextBox in modern versions of dotnet also uses GDI. Therefore, in order for your manual drawing to exactly match the text in it, you should use TextRenderer.DrawText .


I suggest to try the following code:

 public Form1() { //InitializeComponent(); this.Size = new Size(1200, 400); string text = "Hello world"; Font font = new Font("Calibri", 20); var label = new Label { Parent = this, Text = text, BackColor = Color.LightYellow, AutoSize = true, Font = font }; label.MouseDown += (o, e) => { label.UseCompatibleTextRendering = !label.UseCompatibleTextRendering; }; this.MouseDown += (o, e) => { label.Visible = !label.Visible; }; this.Paint += (o, e) => { if (label.UseCompatibleTextRendering) e.Graphics.DrawString(text, font, new SolidBrush(label.ForeColor), label.Location); else TextRenderer.DrawText(e.Graphics, text, font, label.Location, label.ForeColor); }; this.MouseWheel += (o, e) => { var size = font.Size + e.Delta / 5; if (size < 5) size = 5; if (size > 200) size = 200; font = new Font("Calibri", size); this.Refresh(); label.Font = font; }; } 

Place it in the form constructor.
For brevity, designed event handlers lambdas.

Having started the application, you can click on the label - this will change its property UseCompatibleTextRendering - it should be clearly visible how the font is changing.

By clicking on the form you can hide and show the label. Directly below this label, the same text is drawn on the form using TextRenderer.DrawText or Graphics.DrawString , depending on the label property. I have a perfect match in both cases.

Use the mouse wheel to change the font size, to better check whether the drawing is the same or not.


The problem of Windows Forms is a strong DPI dependency. I have Windows 10, all default settings. However, I tried to zoom now, turned off / turned on ClearType - in all cases the drawing is completely the same.


As for drawing in Bitmap. Here you need to set both the properties of the bitmap itself (resolution, etc.) and the parameters in the DrawImage (GraphicsUnit) method. Here I pass.

  • @ Valery - updated answer - Alexander Petrov
  • Well, yes, it is now drawn in the same place, except for the case if you poke on the label itself. There, the text is shifting all the time, but this is due to the fact that at this time, different drawings work. It's strange why my text got crooked when I used e.Graphics . Then I review my code. On the bitmap account, I think to do the following: redraw first on the pictureBox, and from there, using DrawToBitmap on the bitmap. It should turn out fine. In general, ideally, I need to do this with the help of textBox, I will try to have fun with it later. Thanks for the detailed answers - Valeriy