应用中,绘图功能是很常见的,如验证码、特殊的卡证创建和打印等功能;.NET Framework类库中关于绘图的功能主要封装在System.Drawing命名空间,其中还包括一些下级命名空间,具体应用时会给出说明。

此外,对于命名行项目,默认是不引用System.Drawing命名空间的,需要我们在“解决方案资源管理器”中,使用“引用”的右键菜单添加资源引用,选择内容如下图所示。

enter image description here

首先,我们了解了绘图的基本操作资源,主要包含Graphics、Bitmap、Color、Brush、Pen、Font等类型,它们都定义在System.Drawing命名空间。下面的代码会创建一个200*200像素的填充正方形(红色),然后画两条对角线(黄色)。

using System.Drawing;
using System.Drawing.Imaging;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (Bitmap bmp = new Bitmap(200, 200))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.Clear(Color.Red);
                    g.DrawLine(Pens.Yellow, 0, 0, 199, 199);
                    g.DrawLine(Pens.Yellow, 0, 199, 199, 0);
                    //
                    bmp.Save(@"D:\test.png", ImageFormat.Png);
                }
            }
        }
    }
}

执行后,我们可以在D:\test.png查看结果(你也可以修改自己的文件存放位置),如下图所示。

enter image description here

本例演示了图像绘制的基本操作过程。首先,创建了一个Bitmap对象,构造函数中定义了宽度(Width)和高度(Height),其单位是像素(Pixer);然后,定义了Graphics对象,使用静态方法FromImage()关联了Bitmap对象;接下来的绘制工作,实际上就是调用了Graphics对象中的一系列方法(稍后讨论);最后,使用Bitmap对象的Save()方法保存图片,并指定图片为PNG格式。

从示例中,我们可以看到,主要的绘制工作是由Graphics类中的一系列方法完成的,常用的方法包括:

  • Clear()方法,用于清理绘制对象,并可以指定颜色,如上例中就将背景色设置为红色(Color.Red值)。
  • 一系列的DrawXXX()方法,用于绘制线条图形、文本或Image对象,如DrawLine()、DrawRectangle()、DrawEllipse()、DrawPie()、DrawArc()、DrawPolygon()、DrawString()、DrawImage()等方法。
  • 一系列的FillXXX()方法,用于绘制填充图片,如FillRectangle()、FillEllipse()、FillPie()、FillPolygon()等方法。

相关的资源主要包括:

  • Color结构,描述使用红(Red)、绿(Green)、蓝(Blue)及透明度(Alpha)表示的颜色值;其中定义了一些常用的颜色,如Red、Green、Blue、White、Black等等。
  • Brush类,定义填充图形的格式刷的基类,可以使用Brushes类中定义的一些常用填充色格式刷对象,如Brushes.Red就是使用红色格式刷。
  • Pen类,定义绘制图形的画笔对象,可以使用Pens中定义的一些标准色画笔,请注意,这些画笔对象都是1像素的宽度,如果需要,可以自定义Pen对象。
  • Font类,定义绘制文件的字体。

接下来,我们再通过一个示例进一步了解这些资源的应用。这里,我们解决像素和实际尺寸的问题。比如,一个证件需要打印一定的尺寸(假设为100mm*60mm),这种情况应该如何处理呢?

这里需要了解DPI的概念,即每英寸的点数(dots per inch),这里的DPI也可以理解为PPI,即每英寸的像素数(pixers per inch)。知道了DPI和像素值,就可以推算出实际的尺寸了,反之亦然。

下面的代码,我们就来绘制一个100mm*60mm的图像,并可以保存或直接打印输出。

using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // 计算相关数据
            // 毫米尺寸
            float mmWidth = 100f, mmHeight = 60f;
            // DPI
            float dpi = 300f;
            // 每毫米多少点
            float rate = dpi / 25.4f;
            // Bitmap尺寸(像素)
            int width = (int)(mmWidth * rate);
            int height = (int)(mmHeight * rate);
            // 
            using (Bitmap bmp = new Bitmap(width, height))
            {
                // 设置Bitmap对象的DPI
                bmp.SetResolution(dpi, dpi);
                //
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.Clear(Color.LightGray);
                    // 绘制矩形
                    Pen p = new Pen(Color.Black, 5f);
                    g.DrawRectangle(p, 5, 5, bmp.Width - 10, bmp.Height - 10);
                    // 绘制文本
                    Font f = new Font("黑体", 10f, FontStyle.Bold, GraphicsUnit.Millimeter);
                    g.DrawString("HELLO", f, Brushes.Black, 50, 50);
                    // 保存图片
                    bmp.Save(@"D:\test.png", ImageFormat.Png);
                    // 打印图片
                    PrintDocument pdoc = new PrintDocument();
                    pdoc.PrintPage += (object s, PrintPageEventArgs e) =>
                    {
                        e.Graphics.DrawImage(bmp, 0, 0);
                    };
                    pdoc.Print();
                }
            }
        }
    }
}

执行代码,如果计算机连接有打印机,则会打印输出,同时,在D:\test.png文件可以看到如下图所示图像。

enter image description here

实际应用中,我们可以将使用毫米单位的图像操作封装为一个类,并根据需要扩展其成员,以适应实际开发工作。

CHY软件小屋原创作品!