简体   繁体   English

图形DrawString将文本正确放置在System.Label上

[英]Graphics DrawString to Exactly Place Text on a System.Label

I have overridden the OnPaint method of my Label control in VS2008: 我在VS2008中覆盖了我的Label控件的OnPaint方法:

void Label_OnPaint(object sender, PaintEventArgs e) {
  base.OnPaint(e);
  dim lbl = sender as Label;
  if (lbl != null) {
    string Text = lbl.Text;
    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    if (myShowShadow) { // draw the shadow first!
      e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(myShadowColor), myShadowOffset, StringFormat.GenericDefault);
    }
    e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(lbl.ForeColor), 0, 0, StringFormat.GenericDefault);
  }
}

This works, but I really want to find out how to center the text both vertically and horizontally. 这有效,但我真的想知道如何垂直和水平居中文本。 I've heard of the MeasureString() method, but my "Text" complicates matters because it could include page breaks. 我听说过MeasureString()方法,但是我的“文本”使问题变得复杂,因为它可能包含分页符。

Could someone guide me with how to do this? 有人可以指导我如何做到这一点?

Alternatively you can create your own StringFormat object and pass it in using an overload of DrawString that supports a RectangleF: 或者,您可以创建自己的StringFormat对象,并使用支持RectangleF的DrawString重载传递它:

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

RectangleF rectangle = new RectangleF(0, 0, lbl.Width, lbl.Height);

e.Graphics.DrawString(Text, lbl.Font, new SolidBrush(lbl.ForeColor), rectangle, formatter);

您可以使用HorizontalCenterVerticalCenter标志调用TextRenderer.DrawText

Here is the code i'm using at the moment, 这是我目前正在使用的代码,

SizeF size;
string text = "Text goes here";
size = e.Graphics.MeasureString(text, font);
x = (lineWidth / 2) - (size.Width / 2);
y = top;
e.Graphics.DrawString(text, font, Brushes.Black, x, y);

I just wanted to add (a year later) a tool I created because StringAlignment turned out to be not very dependable. 我只想添加(一年后)我创建的工具,因为StringAlignment结果不是很可靠。 It turns out to be very similar to Neo's version. 事实证明它与Neo的版本非常相似。

The code below does an excellent job of centering the text both vertically and horizontally. 下面的代码可以很好地垂直和水平地对齐文本。 Also, I wrote it with various overloads so that different options could be supplied to make this control behave exactly like I want. 此外,我用各种重载编写它,以便可以提供不同的选项,使这个控件的行为完全像我想要的那样。

Here are my overloads: 这是我的重载:

private static void DrawCenter(Label label, Graphics graphics) {
  DrawCenter(label.Text, label, label.Location, label.ForeColor, graphics);
}

private void DrawCenter(string text, Label label, Graphics graphics) {
  DrawCenter(text, label, label.Location, label.ForeColor, graphics);
}

private static void DrawCenter(string text, Label label, Point location, Graphics graphics) {
  DrawCenter(text, label, location, label.ForeColor, graphics);
}

private static void DrawCenter(string text, Label label, Point location, Color fontColor, Graphics graphics) {
  Rectangle rect = new Rectangle(location, label.Size);
  SizeF lSize = graphics.MeasureString(text, label.Font, rect.Width);
  PointF lPoint = new PointF(rect.X + (rect.Width - lSize.Width) / 2, rect.Y + (rect.Height - lSize.Height) / 2);
  graphics.DrawString(text, label.Font, new SolidBrush(fontColor), lPoint);
}

To use these for the Label's OnPaint event, simply modify my original code in the question to following: 要将这些用于Label的OnPaint事件,只需将问题中的原始代码修改为以下内容:

private void Label_OnPaint(object sender, PaintEventArgs e) {
  base.OnPaint(e);
  Label lbl = sender as Label;
  if (lbl != null) {
    string txt = lbl.Text;
    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    if (myShowShadow) { // draw the shadow first!
      Point offset = new Point(lbl.Location.X - 1, lbl.Location.Y - 1)
      DrawCenter(txt, lbl, offset, myShadowColor, e.Graphics);
    }
    DrawCenter(lbl, e.Graphics);
  }
}

For a Print_Document event, I have a version that will also print a box around the label if there is already a box around it in the designer: 对于Print_Document事件,我有一个版本,如果设计器中已经有一个框,它还会在标签周围打印一个框:

private static void DrawCenter(string text, Label label, Point location, Color fontColor, Graphics graphics) {
  Rectangle rect = new Rectangle(location, label.Size);
  SizeF lSize = graphics.MeasureString(text, label.Font, rect.Width);
  PointF lPoint = new PointF((rect.Width - lSize.Width) / 2, (rect.Height - lSize.Height) / 2);
  graphics.DrawString(text, label.Font, new SolidBrush(fontColor), lPoint);
  if (label.BorderStyle != BorderStyle.None) {
    using (Pen p = new Pen(Color.Black)) {
      graphics.DrawRectangle(p, rect);
    }
  }
}

If you find this at all useful, give me a +1. 如果您觉得这很有用,请给我一个+1。

~Joe 〜乔

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

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