Графика DrawString для точного размещения текста в System.Label - PullRequest
4 голосов
/ 07 апреля 2010

Я переопределил OnPaint моего элемента управления Label в VS2008:

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

Это работает, но я действительно хочу выяснить, как центрировать текст как по вертикали, так и по горизонтали. Я слышал о методе MeasureString(), но мой «Текст» усложняет ситуацию, потому что он может включать разрывы страниц.

Может ли кто-нибудь подсказать мне, как это сделать?

Ответы [ 4 ]

9 голосов
/ 07 апреля 2010

В качестве альтернативы вы можете создать свой собственный объект StringFormat и передать его, используя перегрузку DrawString, которая поддерживает RectangleF:

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);
3 голосов
/ 07 апреля 2010

Вы можете позвонить TextRenderer.DrawText с флагами HorizontalCenter и VerticalCenter.

2 голосов
/ 27 сентября 2011

Вот код, который я сейчас использую,

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);
1 голос
/ 03 августа 2012

Я просто хотел добавить (год спустя) инструмент, который я создал, потому что StringAlignment оказался не очень надежным. Оказывается, очень похоже на версию Neo.

Приведенный ниже код отлично справляется с центрированием текста как по вертикали, так и по горизонтали. Кроме того, я написал его с различными перегрузками, чтобы можно было использовать разные опции, чтобы этот элемент управления работал точно так, как я хочу.

Вот мои перегрузки:

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

Чтобы использовать их для события 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);
  }
}

Для события 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);
    }
  }
}

Если вам это вообще пригодится, дайте мне +1.

~ Джо

...