Inside OnPaint of a form I am rendering some text on top of an image. For that I call Graphics.DrawString with word wrapping enabled. In order to be able to edit the text I occasionally show (and hide again after editing) an additional TextBox occupying the same rectangle as my hand drawn text and also with word wrapping enabled.
My idea was that the TextBox ought to render the text exactly like the DrawString command. However there appear to be small deviations of text position (and probably text size?). Moreover these deviations seem to vary depending on the chosen font so it is impossible to tune them manually.
While the deviations are not so terrible as such, they lead to irritating consequences when it comes to the automatic word wrapping. For example in the TextBox a word might appear on the second line while it might appear on the first line when rendered with DrawString after accepting the edit. Most of the time it works but for some rectangle sizes it fails.
If transparency had been available for TextBox, I would have used it instead of rendering text manually, but none of the solutions I found has worked.
Is there any hope that I can find out what settings synchronize the rendering between DrawString and TextBox ? Or is the latter an undocumented implementation detail of the win32 textbox?
The essentials of my code (g is a Graphics object from the paint event args):
stringFormat = new StringFormat(StringFormat.GenericDefault);
stringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.NoClip;
stringFormat.Trimming = StringTrimming.None;
stringFormatAutomaticLinebreak = new StringFormat(StringFormat.GenericDefault);
stringFormatAutomaticLinebreak.FormatFlags = StringFormatFlags.NoClip;
stringFormatAutomaticLinebreak.Trimming = StringTrimming.None;
if (Data.IsAutomaticLinebreak)
{
Rectangle boundingRectangle = new Rectangle(Data.TextPosition.X, Data.TextPosition.Y,
Data.WindowSize.Width-Data.TextPosition.X-1, Data.WindowSize.Height-Data.TextPosition.Y-1);
g.DrawString(Data.Text, Data.TextFont, Data.TextBrush, boundingRectangle, stringFormatAutomaticLinebreak);
}
else
{
g.DrawString(Data.Text, Data.TextFont, Data.TextBrush, Data.TextPosition.X, Data.TextPosition.Y, stringFormat);
}
and
surrogateTextBox = new TextBox();
surrogateTextBox.BorderStyle = BorderStyle.None;
surrogateTextBox.Multiline = true;
surrogateTextBox.Text = Data.Text;
surrogateTextBox.Font = Data.TextFont;
surrogateTextBox.Location = new Point(Data.TextPosition.X,Data.TextPosition.Y);
surrogateTextBox.Size = new Size(Data.WindowSize.Width-Data.TextPosition.X-1, Data.WindowSize.Height-Data.TextPosition.Y-1);
surrogateTextBox.WordWrap = Data.IsAutomaticLinebreak;
Controls.Add(surrogateTextBox);