【问题标题】:Center text output from Graphics.DrawString()居中来自 Graphics.DrawString() 的文本输出
【发布时间】:2008-08-11 17:37:57
【问题描述】:

我正在使用 .NETCF (Windows Mobile) 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 类手动执行此操作。

【问题讨论】:

    标签: c# graphics compact-framework


    【解决方案1】:

    我想为 StringFormat 对象添加另一票。 您可以简单地使用它来指定“中心,中心”,文本将在矩形或提供的点中居中绘制:

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

    但是在 CF 中存在一个问题。如果您对这两个值都使用 Center,那么它会关闭 TextWrapping。不知道为什么会发生这种情况,这似乎是 CF 的一个错误。

    【讨论】:

      【解决方案2】:

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

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

      请注意,此处的文本在给定的范围内对齐。在此示例中,这是 ClientRectangle。

      【讨论】:

      • Chris 的解决方案很棒。顺便说一句,如果你想在水平中心设置,但在任何位置垂直: e.Graphics.DrawString("My String", this.Font, Brushes.Black, e.CellBounds.Width/2, y, sf); // y 是垂直位置
      • 我使用 graphics.VisibleClipBounds.Width / 2 因为我找不到 .CellBounds 属性,而且效果很好。
      【解决方案3】:

      结合我得到的建议,我想出了这个:

          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() 事件,这样我就不会在每次绘制字母时都调用它。只有在控件大小发生变化时才需要调用它。为了完整起见,我只是将它包含在函数中。

      【讨论】:

        【解决方案4】:

        绘制居中文本:

        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)
        

        【讨论】:

        • 感谢您展示了另一种绘制东西的方法,它确实帮助我解决了中心对齐问题 结果 TextRenderer.DrawText 比简单的 e.graphics.drawstring 更精确 非常感谢,投票赞成我:)
        【解决方案5】:

        这里有一些代码。这假设您在表单或 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 部分(例如,您没有使用它)是给您带来困难的原因。

        【讨论】:

          【解决方案6】:

          您可以使用传递给DrawString 方法的StringFormat 对象的实例来使文本居中。

          请参阅 Graphics.DrawString MethodStringFormat Class

          【讨论】:

            猜你喜欢
            • 2015-02-26
            • 2020-02-02
            • 2013-10-05
            • 2018-01-16
            • 2018-10-21
            • 1970-01-01
            • 2014-09-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多