Класс GraphicsPath вычисляет размер объекта Text другим способом (как уже отмечалось в комментариях). Размер текста рассчитывается с использованием размера ограничивающего прямоугольника Ems
.
Em
- это типографская мера, которая не зависит от контекста устройства назначения.
Это относится к прямоугольнику, занимаемому самой широкой буквой шрифта, обычно буквой «М» (произносится em ).
Размер назначения Em
может быть рассчитан двумя различными способами: один включает Font
descent
, другой не включает его. Последнее чаще встречается (так как «М» не имеет descent
частей).
float EMSize = (Font.Height * [FontFamly].GetCellAscent([FontStyle])
/ [FontFamily].GetEmHeight([FontStyle]
или
float EMSize = (Font.Height * ([FontFamly].GetCellAscent([FontStyle] +
[FontFamily.GetCellDescent([FontStyle]))
/ [FontFamily].GetEmHeight([FontStyle]
См. Документы о:
FontFamily.GetEmHeight , FontFamily.GetCellAscent и FontFamily.GetCellDescent
Я вставляю сюда рисунок, который вы можете найти в Документах.
![Font Ascent-Descent](https://i.stack.imgur.com/fOJuI.png)
См. Общую информацию, содержащуюся здесь:
Использование шрифта и текста (MSDN)
В этом документе рассказывается о том, как переводить баллы, пиксели и символы:
Как: получить метрику шрифта (MSDN)
Я предполагаю, что у вас уже есть объект класса, который содержит / ссылается на настройки шрифта, которые поступают из элементов управления пользовательского интерфейса и требуемых настроек.
Я добавляю один с некоторыми свойствами, которые содержат подмножество этих настроек, связанных с вопросом.
Этот класс выполняет некоторые вычисления на основе размера шрифта, выбранного пользователем.
Размер шрифта обычно указывается в Points
. Затем эта мера преобразуется в Pixels
с использованием текущего разрешения экрана DPI
(или преобразуется в Points
из измерения Pixel
). Каждая мера также конвертируется в Ems
, что очень удобно, если вам нужно использовать GraphicsPath
для рисования текста.
Размер Ems
рассчитывается с учетом Ascent
и Descent
шрифта. GraphicsPath
лучше работает с этой мерой, поскольку смешанный текст может иметь обе части, а если нет, то эта часть равна = 0.
Чтобы рассчитать контейнер контейнера для текста, нарисованного с определенным размером шрифта и шрифта, используйте метод GraphicsPath.GetBounds () :
([Canvas]
- это элемент управления, который предоставляет e.Graphics
объект Paint
)
using (GraphicsPath path = new GraphicsPath())
using (StringFormat format = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap))
{
format.Alignment = [StringAlignment.Center/Near/Far]; //As selected
format.LineAlignment = [StringAlignment.Center/Near/Far]; //As selected
//Add the Text to the GraphicsPath
path.AddString(fontObject.Text, fontObject.FontFamily,
(int)fontObject.FontStyle, fontObject.SizeInEms,
[Canvas].ClientRectangle, format);
//Ems size (bounding rectangle)
RectangleF TextBounds = path.GetBounds(null, fontObject.Outline);
//Location of the Text
fontObject.Location = TextBounds.Location;
}
Нарисуйте текст на устройстве [Canvas]
Контекст:
private void Canvas_Paint(object sender, PaintEventArgs e)
{
using (GraphicsPath path = new GraphicsPath())
using (StringFormat format = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap))
{
format.Alignment = [StringAlignment.Center/Near/Far]; //As selected
format.LineAlignment = [StringAlignment.Center/Near/Far]; //As selected
path.AddString(fontObject.Text, fontObject.FontFamily, (int)fontObject.FontStyle, fontObject.SizeInEms, Canvas.ClientRectangle, format);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.CompositingMode = CompositingMode.SourceOver;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
if (fontObject.Outlined) {
e.Graphics.DrawPath(fontObject.Outline, path);
}
using(SolidBrush brush = new SolidBrush(fontObject.FillColor)) {
e.Graphics.FillPath(brush, path);
}
}
}
Визуальный эффект с использованием этого класса и методов realted:
![Font Outline Example](https://i.stack.imgur.com/nCqc3.gif)
Объект класса, для использования в качестве ссылки:
public class FontObject
{
private float CurrentScreenDPI = 0.0F;
private float m_SizeInPoints = 0.0F;
private float m_SizeInPixels = 0.0F;
public FontObject()
: this(string.Empty, FontFamily.GenericSansSerif, FontStyle.Regular, 18F) { }
public FontObject(string Text, Font font)
: this(Text, font.FontFamily, font.Style, font.SizeInPoints) { }
public FontObject(string Text, FontFamily fontFamily, FontStyle fontStyle, float FontSize)
{
if (FontSize < 3) FontSize = 3;
using (Graphics g = Graphics.FromHwndInternal(IntPtr.Zero)) {
this.CurrentScreenDPI = g.DpiY;
}
this.Text = Text;
this.FontFamily = fontFamily;
this.SizeInPoints = FontSize;
this.FillColor = Color.Black;
this.Outline = new Pen(Color.Black, 1);
this.Outlined = false;
}
public string Text { get; set; }
public FontStyle FontStyle { get; set; }
public FontFamily FontFamily { get; set; }
public Color FillColor { get; set; }
public Pen Outline { get; set; }
public bool Outlined { get; set; }
public float SizeInPoints {
get => this.m_SizeInPoints;
set { this.m_SizeInPoints = value;
this.m_SizeInPixels = (value * 72F) / this.CurrentScreenDPI;
this.SizeInEms = GetEmSize();
}
}
public float SizeInPixels {
get => this.m_SizeInPixels;
set { this.m_SizeInPixels = value;
this.m_SizeInPoints = (value * this.CurrentScreenDPI) / 72F;
this.SizeInEms = GetEmSize();
}
}
public float SizeInEms { get; private set; }
public PointF Location { get; set; }
public RectangleF DrawingBox { get; set; }
private float GetEmSize()
{
return (this.m_SizeInPoints *
(this.FontFamily.GetCellAscent(this.FontStyle) +
this.FontFamily.GetCellDescent(this.FontStyle))) /
this.FontFamily.GetEmHeight(this.FontStyle);
}
}
Редактировать
ComboBox с семействами шрифтов.
Настройка OwnerDraw
ComboBox
:
string[] FontList = FontFamily.Families.Where(f => f.IsStyleAvailable(FontStyle.Regular)).Select(f => f.Name).ToArray();
cboFontFamily.DrawMode = DrawMode.OwnerDrawVariable;
cboFontFamily.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
cboFontFamily.AutoCompleteSource = AutoCompleteSource.CustomSource;
cboFontFamily.AutoCompleteCustomSource.AddRange(FontList);
cboFontFamily.DisplayMember = "Name";
cboFontFamily.Items.AddRange(FontList);
cboFontFamily.Text = "Arial";
Обработчики событий:
private void cboFontFamily_DrawItem(object sender, DrawItemEventArgs e)
{
TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
using (FontFamily family = new FontFamily(cboFontFamily.GetItemText(cboFontFamily.Items[e.Index])))
using (Font font = new Font(family, 10F, FontStyle.Regular, GraphicsUnit.Point)) {
TextRenderer.DrawText(e.Graphics, family.Name, font, e.Bounds, cboFontFamily.ForeColor, flags);
}
e.DrawFocusRectangle();
}
private void cboFontFamily_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = (int)this.Font.Height + 4;
}
private void cboFontFamily_SelectionChangeCommitted(object sender, EventArgs e)
{
fontObject.FontFamily = new FontFamily(cboFontFamily.GetItemText(cboFontFamily.SelectedItem));
Canvas.Invalidate();
}