2008-08-11 83 views
38

我使用.NETCF(Windows Mobile)Graphics类和DrawString()方法将单个字符呈现在屏幕上。Graphics.DrawString()的中心文本输出

问题是我似乎无法正确地居中。无论我为字符串渲染位置的Y坐标设置了什么,它总是低于此值,而文本大小越大,Y偏移量越大。

例如,在文本大小12,偏移量是约4,但在32偏移量为约10。

我想要的字符垂直占用大部分矩形的它被吸入并居中水平。这是我的基本代码。 this所引用它在被抽中的用户控制。

Graphics g = this.CreateGraphics(); 

float padx = ((float)this.Size.Width) * (0.05F); 
float pady = ((float)this.Size.Height) * (0.05F); 

float width = ((float)this.Size.Width) - 2 * padx; 
float height = ((float)this.Size.Height) - 2 * pady; 

float emSize = height; 

g.DrawString(letter, new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular), 
      new SolidBrush(Color.Black), padx, pady); 

是的,我知道有,我可以代替使用和设置与定心标签控制,但实际上我需要用手工做Graphics班。

回答

13

通过对我的建议组合,我想出了这个:

private void DrawLetter() 
    { 
     Graphics g = this.CreateGraphics(); 

     float width = ((float)this.ClientRectangle.Width); 
     float height = ((float)this.ClientRectangle.Width); 

     float emSize = height; 

     Font font = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular); 

     font = FindBestFitFont(g, letter.ToString(), font, this.ClientRectangle.Size); 

     SizeF size = g.MeasureString(letter.ToString(), font); 
     g.DrawString(letter, font, new SolidBrush(Color.Black), (width-size.Width)/2, 0); 

    } 

    private Font FindBestFitFont(Graphics g, String text, Font font, Size proposedSize) 
    { 
     // Compute actual size, shrink if needed 
     while (true) 
     { 
      SizeF size = g.MeasureString(text, font); 

      // It fits, back out 
      if (size.Height <= proposedSize.Height && 
       size.Width <= proposedSize.Width) { return font; } 

      // Try a smaller font (90% of old size) 
      Font oldFont = font; 
      font = new Font(font.Name, (float)(font.Size * .9), font.Style); 
      oldFont.Dispose(); 
     } 
    } 

到目前为止,这个完美的作品。

我会改变的唯一事情就是将FindBestFitFont()调用移动到OnResize()事件,以便每次绘制字母时都不会调用它。只有在控件大小发生变化时才需要调用它。我只是将它包含在函数中以获得完整性。

1

这是一些代码。这假定您正在窗体或UserControl上执行此操作。

Graphics g = this.CreateGraphics(); 
SizeF size = g.MeasureString("string to measure"); 

int nLeft = Convert.ToInt32((this.ClientRectangle.Width/2) - (size.Width/2)); 
int nTop = Convert.ToInt32((this.ClientRectangle.Height/2) - (size.Height/2)); 

从您的文章看来,它听起来像ClientRectangle部分(因为您不使用它)是什么给你带来困难。

8

要绘制居中文本:

TextRenderer.DrawText(g, "my text", Font, Bounds, ForeColor, BackColor, 
    TextFormatFlags.HorizontalCenter | 
    TextFormatFlags.VerticalCenter | 
    TextFormatFlags.GlyphOverhangPadding); 

确定最佳字体大小设置为填充区域是比较困难的。我发现的一个有效的尝试是反复试验:从一个大字体开始,然后重复测量字符串并缩小字体直到适合。

Font FindBestFitFont(Graphics g, String text, Font font, 
    Size proposedSize, TextFormatFlags flags) 
{ 
    // Compute actual size, shrink if needed 
    while (true) 
    { 
    Size size = TextRenderer.MeasureText(g, text, font, proposedSize, flags); 

    // It fits, back out 
    if (size.Height <= proposedSize.Height && 
     size.Width <= proposedSize.Width) { return font; } 

    // Try a smaller font (90% of old size) 
    Font oldFont = font; 
    font = new Font(font.FontFamily, (float)(font.Size * .9)); 
    oldFont.Dispose(); 
    } 
} 

你会使用这个为:

Font bestFitFont = FindBestFitFont(g, text, someBigFont, sizeToFitIn, flags); 
// Then do your drawing using the bestFitFont 
// Don't forget to dispose the font (if/when needed) 
+0

谢谢你展示其他方式来绘制东西,它真的帮助我与中心对齐问题结果TextRenderer.DrawText更精确,然后一个简单的e.graphics.drawstring非常感谢,从我投票:) – 2015-02-03 12:55:53

54

我想为StringFormat对象添加另一个投票。 您可以使用此简单地指定“中心,中心”和文本将集中在矩形中画或点提供:

StringFormat format = new StringFormat(); 
format.LineAlignment = StringAlignment.Center; 
format.Alignment = StringAlignment.Center; 

但是这里有一个问题与此的CF.如果您使用Center作为两个值,则会关闭TextWrapping。不知道为什么会发生这种情况,这似乎是CF的一个错误。

40

要对齐文本使用以下命令:

StringFormat sf = new StringFormat(); 
sf.LineAlignment = StringAlignment.Center; 
sf.Alignment = StringAlignment.Center; 
e.Graphics.DrawString("My String", this.Font, Brushes.Black, ClientRectangle, sf); 

请注意,这里的文本在给定的范围对齐。在这个例子中,这是ClientRectangle。

+0

克里斯的解决方案非常棒。顺便说一句,如果你想设置在水平中心,但在任何位置垂直:e.Graphics.DrawString(“我的字符串”,this.Font,Brushes.Black,e.CellBounds.Width/2,Y,SF); // y是垂直位置 – camino 2017-01-27 13:55:03