默认情况下条码打印机是不能打印汉字的, 不过条码打印机是支持上传自定义字体的, 但是这个字体库跟windows里面的字体库肯定不是一回事, 起初我觉得最好能通过上传字体来实现打印汉字, 但是大概研究了一下, 发现这个太复杂, 而且字体库文件也无从搞到, 所以换了方向, 考虑将汉字画成图片, 通过打印图片的方式来实现打印汉字.

所以总的过程为: 将需要打印的汉字在服务器上通过GDI画成图片, 然后将图片按照条码打印机的要求序列化成字符串上传到打印机, 最后通过打印图片命令将其打印出来.

具体的实现方式为:

1. 绘图.

protected Bitmap CreateImage(string data, Font f)

if (string.IsNullOrEmpty(data))

return null;

var txt = new TextBox();

txt.Text = data;

txt.Font = f;

//txt.PreferredSize.Height只能取到一行的高度(连边距)

//所以需要乘以行数, 但是必须先减掉边距, 乘了以后,再把边距加上.

//5是目测的边距

var image = new Bitmap(txt.PreferredSize.Width, (txt.PreferredSize.Height - 5) * txt.Lines.Length + 5);

var g = Graphics.FromImage(image);

var b = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Black, Color.Black, 1.2f, true);

g.Clear(System.Drawing.Color.White);

g.DrawString(data, f, b, 1, 1);

return image;

将需要打印的汉字和字体作为参数传入, 即可得到一副图片.

2. 转换并序列化图片.

protected string ConvertImageToCode(Bitmap img)

var sb = new StringBuilder();

long clr = 0, n = 0;

int b = 0;

for (int i = 0; i &lt img.Size.Height; i++)

for (int j = 0; j &lt img.Size.Width; j++)

b = b * 2;

clr = img.GetPixel(j, i).ToArgb();

string s = clr.ToString("X");

if (s.Substring(s.Length - 6, 6).CompareTo("BBBBBB") &lt 0)

if (j == (img.Size.Width - 1))

if (n &lt 8)

b = b * (2 ^ (8 - (int)n));

sb.Append(b.ToString("X").PadLeft(2, '0'));

b = 0;

n = 0;

if (n &gt= 8)

sb.Append(b.ToString("X").PadLeft(2, '0'));

b = 0;

n = 0;

sb.Append(System.Environment.NewLine);

return sb.ToString();

这是将图片转换为条码打印机能够支持的点阵图.

3. 通过ZPL将图片上传:

var t = ((img.Size.Width / 8 + ((img.Size.Width % 8 == 0) ? 0 : 1)) * img.Size.Height).ToString();

var w =