我有一个winform应用程序,我在其上放置了一个标签。我从后台线程动态更改标签的文本。文本更改会触发一个应该调整标签大小的事件。一切正常,但我测量的字符串长度不正确,因此标签的客户端大小不正确。
protected void progressInfo_TextChanged(object sender, EventArgs e)
{
// Auto size label to fit the text
// ... create a Graphics object for the label
Graphics g_progressInfo = this.progressInfo.CreateGraphics();
// ----------------
// Set up string.
string text1 = "Reading data from input data file ... inputData";
Font stringFont = new System.Drawing.Font("Verdana", 8,
System.Drawing.FontStyle.Regular);
Size textSize = TextRenderer.MeasureText(text1, stringFont);
TextRenderer.DrawText(g_progressInfo, text1, stringFont,
new Rectangle(new Point(10, 10), textSize), Color.Red);
System.Diagnostics.Debug.WriteLine("textSize = " + (textSize).ToString());
// ----------------
// Set the TextRenderingHint property.
g_progressInfo.TextRenderingHint =
System.Drawing.Text.TextRenderingHint.AntiAlias;
// ... get the Size needed to accommodate the formatted text
Size preferredSize_progressInfo = g_progressInfo.MeasureString(
this.progressInfo.Text, this.progressInfo.Font).ToSize();
System.Diagnostics.Debug.WriteLine("preferredSize_progressInfo = " +
(preferredSize_progressInfo).ToString());
/*
g_progressInfo.MeasureString above calculates the size of the string as floting
point numbers that get truncated by .ToSize().
... pad the text by 1 pixel, and resize the label
*/
System.Diagnostics.Debug.WriteLine("this.progressInfo.ClientSize = " +
(this.progressInfo.ClientSize).ToString());
this.progressInfo.ClientSize = new Size(
preferredSize_progressInfo.Width + 10, preferredSize_progressInfo.Height + 1);
System.Diagnostics.Debug.WriteLine("this.progressInfo.ClientSize = " +
(this.progressInfo.ClientSize).ToString());
// ... clean up the Graphics object
g_progressInfo.Dispose();
}
以下是调试的输出:
Result from TextRenderer ---> textSize = {Width=270, Height=13}
Size calculated by MeasureString() ---> preferredSize_progressInfo = {Width=260, Height=14}
Initial label client size ---> progressInfo.ClientSize = {Width=100, Height=23}
Resized client size based on MeasureString ---> this.progressInfo.ClientSize = {Width=270, Height=15}
问题是计算的字符串宽度相差10个像素。事实证明,TextRenderer计算的宽度(宽度= 270)是正确的,而MeasureString计算的宽度(宽度= 260)是不正确的,因为它将输入字符串的显示截断为:“从输入数据文件中读取数据。 ..输入“。我还尝试使用MeasureCharacterRanges()测量字符串宽度,这种方法产生的结果类似于MeasureString方法产生的结果。 TextRenderer计算的大小似乎正确显示文本。
是的,据我所知,如果是这种情况我应该只使用TextRenderer,但有人可以向我解释各种方法计算出的字符串宽度如此巨大差异的根源吗?任何帮助或指导将不胜感激。谢谢。
答案 0 :(得分:1)
我实际上找到了答案。它是在stackoverflow的早期帖子中标题的 TextRenderer.MeasureText and Graphics.MeasureString mismatch in size并由Sven回答如下:
TextRenderer使用GDI渲染文本,而Graphics使用GDI +。两者使用略有不同的方法来布局文本,因此大小不同。
您应该使用哪一个取决于最终用于实际绘制文本的内容。如果您使用GDI + Graphics.DrawString绘制它,请使用Graphics.MeasureString进行测量。如果您使用GDI TextRenderer.DrawText绘图,请使用TextRenderer.MeasureText进行测量。
如果文本将显示在Windows窗体控件中,则如果UseCompatibleTextRendering设置为false(默认值),它将使用TextRenderer。
我希望在我的控件上添加设置UseCompatibleTextRendering = true改善了情况,但没有完全解决它。这次输入字符串被截断为“从输入数据文件读取数据... inputDa”。因此,似乎使用TextRenderer是获取Winform控件的方法。