【愚公系列】2023年11月 GDI+绘图专题 DrawString

举报
愚公搬代码 发表于 2023/11/29 22:44:35 2023/11/29
【摘要】 🏆 作者简介,愚公搬代码🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物...

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

DrawString是C#中Graphics类的一个方法,用于在指定的位置绘制文本。在WinForm应用程序中使用DrawString,可以在窗体或控件上绘制文本。

以下是使用DrawString方法在WinForm中绘制文本的示例代码:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    string text = "Hello, World!";
    Font font = new Font("Arial", 16);
    Brush brush = Brushes.Black;
    PointF point = new PointF(50, 50);

    g.DrawString(text, font, brush, point);
}

在这里插入图片描述

在上面的示例中,我们使用Graphics类的DrawString方法在Form1的Paint事件中绘制了一个文本字符串。我们创建了一个Graphics对象g并在其上调用DrawString方法。方法的第一个参数是要绘制的文本字符串,第二个参数是要使用的字体,第三个参数是绘制文本的刷子(颜色),第四个参数是文本的位置。

您可以根据需要更改字体,颜色和位置等参数,以根据您的应用程序的需要在窗体或控件上绘制文本。

🚀一、DrawString

🔎1.制表位

在GDI+中,通过使用TabStops属性和StringFormat类,可以在绘图时使用像素或百分比的制表位来对齐文本。这对于制作表格和对齐文本非常有用。下面是一个示例代码,演示如何在WinForm中绘制带有制表符的文本。

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    string text = "Name\tAge\tGender";
    Font font = new Font("Arial", 16);
    Brush brush = Brushes.Black;
    PointF point = new PointF(50, 50);
    StringFormat format = new StringFormat();
    format.SetTabStops(50, new float[] { 100, 200 });

    g.DrawString(text, font, brush, point, format);
}

在这里插入图片描述
在上面的示例中,我们使用Graphics类的DrawString方法在Form1的Paint事件中绘制了一个带有制表符的文本字符串。我们创建了一个Graphics对象g,然后定义了文本字符串,字体,笔刷和位置,以及一个StringFormat对象。我们通过在SetTabStops方法中指定像素值和百分比值来设置制表位。在此示例中,我们在50像素处设置了一个制表位,并在100像素的位置和200像素的位置处指定了两个制表符。这将使文本沿x轴对齐,并在“Name”和“Age”之间以及“Age”和“Gender”之间创建制表符。最后,我们在Graphics对象上调用DrawString方法,指定文本,字体,笔刷,位置和格式。

🔎2.使用笔刷显示文本

不仅可以使用GDI+绘图DrawString方法以文本形式在绘图表面上绘制字符。同时,可以使用HatchBrush笔刷来为绘制的文本添加纹理、阴影等效果。

以下是使用HatchBrush笔刷在WinForm中绘制文本的示例代码:

// 创建绘图表面
Bitmap bmp = new Bitmap(200, 200);
Graphics g = Graphics.FromImage(bmp);

// 创建HatchBrush笔刷
HatchBrush hatchBrush = new HatchBrush(HatchStyle.Cross, Color.Green, Color.Yellow);

// 绘制文本
string text = "HatchBrush Test";
Font font = new Font("Arial", 20);
PointF point = new PointF(20, 70);
g.DrawString(text, font, hatchBrush, point);

// 显示绘制结果
pictureBox1.Image = bmp;

上述代码中,首先创建了一个200x200像素大小的位图和相应的Graphics对象。然后创建了一个HatchBrush对象,并将其作为参数传递给DrawString方法,以绘制文本。最后在pictureBox1中显示绘制结果。

运行上述代码后,将看到绘制了“HatchBrush Test”文本的图片,文本的字体颜色为绿黄相间的格子状。

在这里插入图片描述

此外,还可以使用其他类型的Brush对象来为绘制的文本添加不同的效果。例如,使用LinearGradientBrush可以为文本添加渐变色效果。

🔎3.精确控制文本

🦋3.1 文本居中

在使用GDI+绘制文本时,可以使用DrawString方法来绘制。该方法有多个重载,其中有一个重载可以通过PointF类型的参数来确定文本的起始绘制位置,如下所示:

public void DrawString(string s, Font font, Brush brush, PointF point);

其中s为要绘制的字符串,font为文字的字体样式,brush为文字的填充颜色,point为文字的起始绘制位置。要精确控制文本的位置,可以使用PointF类型的参数来指定起始位置。

例如,要将字符串"Hello, World!"绘制在WinForm的画布中心位置,可以先计算出文本绘制所需的区域大小,然后将文本绘制起始位置设置为画布中心减去文本绘制区域大小的一半,如下所示:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    string text = "Hello, World!";
    Font font = new Font("Arial", 16);
    Brush brush = Brushes.Black;

    // 计算文本绘制所需的区域大小
    SizeF textSize = e.Graphics.MeasureString(text, font);

    // 计算文本绘制起始位置
    PointF startPoint = new PointF(
        (this.ClientSize.Width - textSize.Width) / 2,
        (this.ClientSize.Height - textSize.Height) / 2);

    // 绘制文本
    e.Graphics.DrawString(text, font, brush, startPoint);
}

在这里插入图片描述

在上述代码中,使用Graphics对象的MeasureString方法计算出文本绘制所需的区域大小,然后计算出文本绘制起始位置,并使用DrawString方法进行绘制。这样就可以精确地控制文本的位置。

🦋3.2 精确控制文本

private void OnPaint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.FillRectangle(Brushes.White, this.ClientRectangle);

    FontFamily fontFamily = new FontFamily("宋体");
    int ascentInDU = fontFamily.GetCellAscent(FontStyle.Regular);
    int descentInDU = fontFamily.GetCellDescent(FontStyle.Regular);
    int emHeightInDU = fontFamily.GetEmHeight(FontStyle.Regular);
    int lineSpacingInDU = fontFamily.GetLineSpacing(FontStyle.Regular);

    float emSizeInGU = 100;
    Font font = new Font(fontFamily, emSizeInGU, FontStyle.Regular);

    float ascentInGU = ascentInDU * (emSizeInGU / emHeightInDU);
    float descentInGU = descentInDU * (emSizeInGU / emHeightInDU);
    float lineSpacingInGU = lineSpacingInDU * (emSizeInGU / emHeightInDU);

    HatchBrush hb = new HatchBrush(HatchStyle.Cross, Color.Red);
    PointF textOrig = new PointF(10, 20);
    PointF nextLineTextOrig = new PointF(textOrig.X, textOrig.Y + font.Height);
    g.DrawString("Mg好人", font, hb, textOrig);
    g.DrawString("Mg好人", font, hb, nextLineTextOrig);

    int lineLength = 500;
    g.DrawLine(Pens.Blue, textOrig, new PointF(textOrig.X + lineLength, textOrig.Y));
    g.DrawLine(Pens.Blue, nextLineTextOrig, new PointF(nextLineTextOrig.X + lineLength, nextLineTextOrig.Y));

    PointF p = new PointF(textOrig.X, textOrig.Y + lineSpacingInGU);
    g.DrawLine(Pens.Red, p, new PointF(p.X + lineLength, p.Y));

    g.DrawLine(Pens.Black, new PointF(p.X + lineLength, p.Y), new PointF(p.X + lineLength, p.Y + 153));

    p = new PointF(nextLineTextOrig.X, nextLineTextOrig.Y + lineSpacingInGU);
    g.DrawLine(Pens.Red, p, new PointF(p.X + lineLength, p.Y));

    p = new PointF(textOrig.X, textOrig.Y + lineSpacingInGU - ascentInGU);
    g.DrawLine(Pens.Yellow, p, new PointF(p.X + lineLength, p.Y));
    p = new PointF(nextLineTextOrig.X, nextLineTextOrig.Y + lineSpacingInGU - ascentInGU);
    g.DrawLine(Pens.Yellow, p, new PointF(p.X + lineLength, p.Y));

    p = new PointF(textOrig.X, textOrig.Y + lineSpacingInGU + descentInGU);
    g.DrawLine(Pens.Green, p, new PointF(p.X + lineLength, p.Y));
    p = new PointF(nextLineTextOrig.X, nextLineTextOrig.Y + lineSpacingInGU + descentInGU);
    g.DrawLine(Pens.Green, p, new PointF(p.X + lineLength, p.Y));

    font.Dispose();

}

在这里插入图片描述

  • 红色线:基线,蓝色线到红色线之间的距离就是lineSpacingInGU;
  • 绿色线:红色线到绿色线之间的距离就是descentInGU;
  • 黄线色:黄色线到红色线之间的距离就是ascentInGU;
  • 黑色线:指的是两行红色线之间的距离,也就是行距。

🔎4.文本的质量

GDI+绘图DrawString绘制文本时,可以使用TextRenderingHint属性来提高或降低文本的质量和清晰度。以下是使用TextRenderingHint属性的示例:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;

    // 设置文本呈现质量为抗锯齿
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

    // 绘制文本
    string text = "Hello World!";
    Font font = new Font("Arial", 16);
    Brush brush = Brushes.Black;
    PointF point = new PointF(50, 50);

    g.DrawString(text, font, brush, point);
}

在这里插入图片描述

在上面的示例中,我们将TextRenderingHint属性设置为抗锯齿,以获得更平滑的文本边缘。如果需要更高的性能,则可以将该属性设置为Default或SystemDefault。但是,这可能会牺牲一些文本呈现的质量。

在设置完TextRenderingHint属性后,可以使用DrawString方法来绘制文本。该方法的参数包括文本内容、字体、笔刷、位置等。使用这些参数,可以控制文本的样式、颜色和位置等属性。

🔎5.处理绘图表面的单位以及字体的单位

private void OnPaint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.PageUnit = GraphicsUnit.Inch;
    Pen p = new Pen(Color.Black, 1 / 96f);
    Font f = new Font("Times New Roman", 16);
    string s = "Abc";
    SizeF sf = g.MeasureString(s, f);

    g.DrawRectangle(p, 1, 1, sf.Width, sf.Height);
    g.DrawString(s, f, Brushes.Black, 1, 1);


    f = new Font("Times New Roman", 1, GraphicsUnit.Inch);
    sf = g.MeasureString(s, f);

    g.DrawRectangle(p, 1, 1, sf.Width, sf.Height);
    g.DrawString(s, f, Brushes.Red, 1, 1);

    f.Dispose();
    p.Dispose();
}

在这里插入图片描述

🔎6.测量文本大小

using System.Drawing;
using System.Windows.Forms;

namespace MeasureStringExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            string text = "Hello World";
            Font font = new Font("Arial", 12);
            SizeF size = new SizeF(100, 100);
            Graphics graphics = e.Graphics;
            SizeF textSize = graphics.MeasureString(text, font, size);
            PointF location = new PointF(10, 10);
            graphics.DrawString(text, font, Brushes.Black, location);
            graphics.DrawRectangle(Pens.Red, new RectangleF(location, textSize));
        }
    }
}

在这里插入图片描述
在上面的代码中,我们在 Form1_Paint 事件处理程序中使用MeasureString方法来测量一个字符串的大小,然后在屏幕上绘制该字符串并用红色边框标记该字符串的大小。这个例子中测量的字符串是"Hello World",字体是Arial、大小为12磅,并且大小被限制在100x100的矩形区域内。在绘制字符串时,我们将使用黑色刷子,位置位于(10,10)。

🔎7.StringFormat

DrawString方法有多个重载,其中一个参数是StringFormat类型的格式化对象。StringFormat对象可以设置文本的对齐方式、行距、字间距等等。

以下是一个使用StringFormat对象的示例:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    //创建一个StringFormat对象
    StringFormat stringFormat = new StringFormat();
    stringFormat.Alignment = StringAlignment.Center;
    stringFormat.LineAlignment = StringAlignment.Center;

    //绘制文本
    e.Graphics.DrawString("Hello World!", Font, Brushes.Black, 
        new RectangleF(0, 0, ClientSize.Width, ClientSize.Height), 
        stringFormat);
}

在这里插入图片描述
在上面的代码中,我们创建了一个StringFormat对象,并设置了Alignment和LineAlignment属性来使文本在控件中央对齐。接着,我们使用Graphics对象的DrawString方法来绘制文本,其中第四个参数是绘制文本的矩形区域,第五个参数是我们创建的StringFormat对象。

可以通过设置StringFormat对象的其他属性,来实现不同的文本效果,例如设置Trimming属性来裁剪超出矩形区域的文本,设置TabStops属性来实现文本的制表符对齐等等。

需要注意的是,在使用StringFormat对象时,需要在绘制文本时将其作为参数传递。否则,将无法应用StringFormat对象的属性。


🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

![在这里插入图片描述](https://img-blog.csdnimg.cn/e06a317e89694a23ad89d2c59538c3a1.jpeg#pic_center =450x300)

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。