这个
GraphicsPath
类以不同的方式计算文本对象的大小(如注释中所述)。文本大小是使用
Ems
边框大小。
Em
是独立于目标设备上下文的排版度量。
它指的是字体最宽的字母所占据的矩形,通常是字母“M”(发音)
相对长度单位
目的地
相对长度单位
大小可以用两种不同的方法计算:一种方法包括
Font
descent
float EMSize = (Font.SizeInPoints * [FontFamily].GetCellAscent([FontStyle])
/ [FontFamily].GetEmHeight([FontStyle])
或
float EMSize = (Font.SizeInPoints * ([FontFamily].GetCellAscent([FontStyle] +
[FontFamily.GetCellDescent([FontStyle]))
/ [FontFamily].GetEmHeight([FontStyle])
FontFamily.GetEmHeight
,
FontFamily.GetCellAscent
和
FontFamily.GetCellDescent
我在这里插入你能在文件里找到的数字。
请参阅此处包含的一般信息:
Using Font and Text (MSDN)
本文档报告了有关如何转换点、像素和Ems的详细信息:
How to: Obtain Font Metrics (MSDN)
我假设您已经有一个class对象,它包含/引用来自UI控件的字体设置和所需的调整。
我在这里添加了一个包含这些设置子集的属性,与问题相关。
此类根据用户选择的字体大小执行一些计算。
DPI
分辨率(或从像素维度转换为点)。每个度量值也转换为
Ems公司
,如果您必须使用
GraphicsPath
绘制文本。
Ems公司
Ascent
Descent
字体的名称。
这个
类可以更好地使用这个度量,因为混合文本可以同时包含这两个部分,如果不包含这两个部分,那么该部分就是
= 0
.
GraphicsPath.GetBounds()
方法:
(
[Canvas]
Paint
事件的
e.Graphics
对象)
using (var path = new GraphicsPath())
using (var 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;
}
把文字画在纸上
设备上下文:
private void Canvas_Paint(object sender, PaintEventArgs e)
{
using (var path = new GraphicsPath())
using (var 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.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
// The composition properties are useful when drawing on a composited surface
// when we simply draw on a Control's surface, these are useless
e.Graphics.CompositingMode = CompositingMode.SourceOver;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
if (fontObject.Outlined) {
e.Graphics.DrawPath(fontObject.Outline, path);
}
using(var brush = new SolidBrush(fontObject.FillColor)) {
e.Graphics.FillPath(brush, path);
}
}
}
使用此类和realted方法的视觉效果:
类对象,用作引用:
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);
}
}
:
创建自定义组合框并设置其
DrawMode = OwnerDrawVariable
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)
{
if ((Items.Count == 0) || e.Index < 0) return;
e.DrawBackground();
var flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
using (var family = new FontFamily(cboFontFamily.GetItemText(cboFontFamily.Items[e.Index])))
using (var 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();
}