简体   繁体   English

Graphics.DrawString()的中心文本输出

[英]Center text output from Graphics.DrawString()

I'm using the .NETCF (Windows Mobile) Graphics class and the DrawString() method to render a single character to the screen. 我正在使用.NETCF(Windows Mobile) Graphics类和DrawString()方法将单个字符呈现给屏幕。

The problem is that I can't seem to get it centred properly. 问题是我似乎无法使其正确居中。 No matter what I set for the Y coordinate of the location of the string render, it always comes out lower than that and the larger the text size the greater the Y offset. 无论我为字符串渲染的位置的Y坐标设置什么,它总是低于该值,文本大小越大Y偏移越大。

For example, at text size 12, the offset is about 4, but at 32 the offset is about 10. 例如,在文本大小12处,偏移量约为4,但在32处,偏移量约为10。

I want the character to vertically take up most of the rectangle it's being drawn in and be centred horizontally. 我希望角色垂直占据它所绘制的大部分矩形并水平居中。 Here's my basic code. 这是我的基本代码。 this is referencing the user control it's being drawn in. 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);

Yes, I know there is the label control that I could use instead and set the centring with that, but I actually do need to do this manually with the Graphics class. 是的,我知道我可以使用标签控件并使用它设置居中,但实际上我需要使用Graphics类手动执行此操作。

I'd like to add another vote for the StringFormat object. 我想为StringFormat对象添加另一个投票。 You can use this simply to specify "center, center" and the text will be drawn centrally in the rectangle or points provided: 您可以简单地使用它来指定“center,center”,文本将在矩形或中心提供的中心绘制:

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

However there is one issue with this in CF. 然而,在CF中有一个问题。 If you use Center for both values then it turns TextWrapping off. 如果对两个值都使用中心,则会关闭TextWrapping。 No idea why this happens, it appears to be a bug with the CF. 不知道为什么会这样,它似乎是CF的一个错误。

To align a text use the following: 要对齐文本,请使用以下内容:

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

Please note that the text here is aligned in the given bounds. 请注意,此处的文本在给定范围内对齐。 In this sample this is the ClientRectangle. 在此示例中,这是ClientRectangle。

Through a combination of the suggestions I got, I came up with this: 通过我得到的建议的组合,我想出了这个:

    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();
        }
    }

So far, this works flawlessly. 到目前为止,这完美无瑕。

The only thing I would change is to move the FindBestFitFont() call to the OnResize() event so that I'm not calling it every time I draw a letter. 我唯一要改变的是将FindBestFitFont()调用移动到OnResize()事件,这样我每次绘制一个字母时都不会调用它。 It only needs to be called when the control size changes. 只需在控件大小更改时调用它。 I just included it in the function for completeness. 我只是把它包含在功能中以保持完整性。

To draw a centered text: 要绘制居中文本:

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

Determining optimal font size to fill an area is a bit more difficult. 确定填充区域的最佳字体大小有点困难。 One working soultion I found is trial-and-error: start with a big font, then repeatedly measure the string and shrink the font until it fits. 我找到的一个工作灵魂是试错:从一个大字体开始,然后重复测量字符串并收缩字体直到它适合。

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();
  }
}

You'd use this as: 你用它作为:

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)

You can use an instance of the StringFormat object passed into the DrawString method to center the text. 您可以使用传递给DrawString方法的StringFormat对象的实例来居中文本。

See Graphics.DrawString Method and StringFormat Class . 请参见Graphics.DrawString方法StringFormat类

Here's some code. 这是一些代码。 This assumes you are doing this on a form, or a UserControl. 这假设您在表单或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));

From your post, it sounds like the ClientRectangle part (as in, you're not using it) is what's giving you difficulty. 从你的帖子,它听起来像ClientRectangle部分(因为,你没有使用它)是给你带来困难的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM