今天公司让做一个输入数字、字母生成条形码并且可以以图片格式保存到本地。当看到这个需求时候感觉很搞笑,明明可以用文本框搞定的东西非得做个程序。哎,寄人篱下,不多说了,这就是养兵千日用兵一时。
我在网上找了很多资料,在最终得出的结论就是电脑必须安装有code39/code 128 字体。具体下载地址我就不说,网上很多。我们以code 128 为例开始操作。
首先我们创建一个winform工程,然后通过拖拽方式进行设计界面(第一次创建winform程序,不知道有没有人自己手敲界面,心好累)界面如下:
上下的控件就不解释了,中间我拖拽的是picturebox控件,这个控件用于显示生成的条形码。
代码部分,首先我先创建了一个类Code39,具体代码如下:
1 using System; 2 using System.Drawing; 3 using System.Drawing.Imaging; 4 using System.IO; 5 public sealed class Code39 6 { 7 #region private variables 8 /// <summary> 9 /// The Space Between each of Title, BarCode, BarCodeString 10 /// </summary> 11 private const int SPACE_HEIGHT = 3; 12 SizeF _sizeLabel = SizeF.Empty; 13 SizeF _sizeBarCodeValue = SizeF.Empty; 14 SizeF _sizeBarCodeString = SizeF.Empty; 15 #endregion 16 #region Label 17 private string _label = null; 18 private Font _labelFont = null; 19 /// <summary> 20 /// BarCode Title (条码标签) 21 /// </summary> 22 public string Label 23 { 24 set { _label = value; } 25 } 26 /// <summary> 27 /// BarCode Title Font (条码标签使用的字体) 28 /// </summary> 29 public Font LabelFont 30 { 31 get 32 { 33 if (_labelFont == null) 34 return new Font("Code 128", 10); 35 return _labelFont; 36 } 37 set { _labelFont = value; } 38 } 39 #endregion 40 private string _additionalInfo = null; 41 private Font _addtionalInfoFont = null; 42 /// <summary> 43 /// Additional Info Font (附加信息字体) 44 /// </summary> 45 public Font AdditionalInfoFont 46 { 47 set { _addtionalInfoFont = value; } 48 get 49 { 50 if (_addtionalInfoFont == null) return new Font("Code 128", 10); 51 return _addtionalInfoFont; 52 } 53 } 54 /// <summary> 55 /// Additional Info Content, if "ShowBarCodeValue" is true, the info is unvisible 56 /// 附加信息,如果设置ShowBarCodeValue为true,则此项不显示 57 /// </summary> 58 public string AdditionalInfo 59 { 60 set { _additionalInfo = value; } 61 } 62 #region BarCode Value and Font 63 private string _barCodeValue = null; 64 /// <summary> 65 /// BarCode Value (条码值) 66 /// </summary> 67 public string BarCodeValue 68 { 69 get 70 { 71 if (string.IsNullOrEmpty(_barCodeValue)) 72 throw new NullReferenceException("The BarCodeValue has not been set yet!"); 73 return _barCodeValue; 74 } 75 set { _barCodeValue = value.StartsWith("*") && value.EndsWith("*") ? value : "*" + value + "*"; } 76 } 77 private bool _showBarCodeValue = false; 78 /// <summary> 79 /// whether to show the original string of barcode value bellow the barcode 80 /// 是否在条码下方显示条码值,默认为false 81 /// </summary> 82 public bool ShowBarCodeValue 83 { 84 set { _showBarCodeValue = value; } 85 } 86 private Font _barCodeValueFont = null; 87 /// <summary> 88 /// the font of the codestring to show 89 /// 条码下方显示的条码值的字体 90 /// </summary> 91 public Font BarCodeValueFont 92 { 93 get 94 { 95 if (_barCodeValueFont == null) 96 return new Font("Code 128", 50); 97 return _barCodeValueFont; 98 } 99 set { _barCodeValueFont = value; } 100 } 101 private int _barCodeFontSize = 50; 102 /// <summary> 103 /// the font size of the barcode value to draw 104 /// 条码绘制的大小,默认50 105 /// </summary> 106 public int BarCodeFontSzie 107 { 108 set { _barCodeFontSize = value; } 109 } 110 #endregion 111 #region generate the barcode image 112 private Bitmap BlankBackImage 113 { 114 get 115 { 116 int barCodeWidth = 0, barCodeHeight = 0; 117 using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format32bppArgb)) 118 { 119 using (Graphics g = Graphics.FromImage(bmp)) 120 { 121 if (!string.IsNullOrEmpty(_label)) 122 { 123 _sizeLabel = g.MeasureString(_label, LabelFont); 124 barCodeWidth = (int)_sizeLabel.Width; 125 barCodeHeight = (int)_sizeLabel.Height + SPACE_HEIGHT; 126 } 127 _sizeBarCodeValue = g.MeasureString(BarCodeValue, new Font("Free 3 of 9 Extended", _barCodeFontSize)); 128 barCodeWidth = Math.Max(barCodeWidth, (int)_sizeBarCodeValue.Width); 129 barCodeHeight += (int)_sizeBarCodeValue.Height; 130 if (_showBarCodeValue) 131 { 132 _sizeBarCodeString = g.MeasureString(_barCodeValue, BarCodeValueFont); 133 barCodeWidth = Math.Max(barCodeWidth, (int)_sizeBarCodeString.Width); 134 barCodeHeight += (int)_sizeBarCodeString.Height + SPACE_HEIGHT; 135 } 136 //else 137 //{ 138 // if (!string.IsNullOrEmpty(_additionalInfo)) 139 // { 140 // _sizeAdditionalInfo = g.MeasureString(_additionalInfo, AdditionalInfoFont); 141 // barCodeWidth = Math.Max(barCodeWidth, (int)_sizeAdditionalInfo.Width); 142 // barCodeHeight += (int)_sizeAdditionalInfo.Height + SPACE_HEIGHT; 143 // } 144 //} 145 } 146 } 147 return new Bitmap(barCodeWidth, barCodeHeight, PixelFormat.Format32bppArgb); 148 } 149 } 150 /// <summary> 151 /// Draw the barcode value to the blank back image and output it to the browser 152 /// 绘制WebForm形式的条码 153 /// </summary> 154 /// <param name="ms">Recommand the "Response.OutputStream" 使用 Response.OutputStream</param> 155 /// <param name="imageFormat">The Image format to the Browser 输出到浏览器到图片格式,建议GIF</param> 156 public Bitmap CreateWebForm(Stream ms, ImageFormat imageFormat) 157 { 158 int barCodeWidth, barCodeHeight; 159 using (Bitmap bmp = this.BlankBackImage) 160 { 161 barCodeHeight = bmp.Height; 162 barCodeWidth = bmp.Width; 163 using (Graphics g = Graphics.FromImage(bmp)) 164 { 165 g.Clear(Color.White); 166 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; 167 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 168 int vPos = 0; 169 ////Draw Label String 170 if (!string.IsNullOrEmpty(_label)) 171 { 172 g.DrawString(_label, LabelFont, new SolidBrush(Color.Black), 173 XCenter((int)_sizeLabel.Width, barCodeWidth), vPos); 174 vPos += (int)_sizeLabel.Height + SPACE_HEIGHT; 175 } 176 else { vPos = SPACE_HEIGHT; } 177 ////Draw The Bar Value 178 g.DrawString(_barCodeValue, new Font("Free 3 of 9 Extended", _barCodeFontSize), new SolidBrush(Color.Black), 179 XCenter((int)_sizeBarCodeValue.Width, barCodeWidth), vPos); 180 ////Draw the BarValue String 181 if (_showBarCodeValue) 182 { 183 g.DrawString(_barCodeValue, BarCodeValueFont, new SolidBrush(Color.Black), 184 XCenter((int)_sizeBarCodeString.Width, barCodeWidth), 185 vPos + (int)_sizeBarCodeValue.Height); 186 } 187 //else 188 //{ 189 // if (!string.IsNullOrEmpty(_additionalInfo)) 190 // { 191 // g.DrawString(_additionalInfo, AdditionalInfoFont, new SolidBrush(Color.Black), 192 // XCenter((int)_sizeAdditionalInfo.Width, barCodeWidth), 193 // vPos + (int)_sizeBarCodeValue.Height); 194 // } 195 //} 196 } 197 bmp.Save(ms, imageFormat); 198 return bmp; 199 } 200 } 201 /// <summary> 202 /// 生成winform格式的条码 203 /// </summary> 204 /// <param name="imageFormat">图片格式,建议GIF</param> 205 /// <returns>Stream类型</returns> 206 public Stream CreateWinForm(ImageFormat imageFormat) 207 { 208 int barCodeWidth, barCodeHeight; 209 using (Bitmap bmp = this.BlankBackImage) 210 { 211 barCodeHeight = bmp.Height; 212 barCodeWidth = bmp.Width; 213 using (Graphics g = Graphics.FromImage(bmp)) 214 { 215 g.Clear(Color.White); 216 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; 217 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 218 int vPos = 0; 219 ////Draw Label String 220 if (!string.IsNullOrEmpty(_label)) 221 { 222 g.DrawString(_label, LabelFont, new SolidBrush(Color.Black), 223 XCenter((int)_sizeLabel.Width, barCodeWidth), vPos); 224 vPos += (int)_sizeLabel.Height + SPACE_HEIGHT; 225 } 226 else { vPos = SPACE_HEIGHT; } 227 ////Draw The Bar Value 228 g.DrawString(_barCodeValue, new Font("Free 3 of 9 Extended", _barCodeFontSize), new SolidBrush(Color.Black), 229 XCenter((int)_sizeBarCodeValue.Width, barCodeWidth), vPos); 230 ////Draw the BarValue String 231 if (_showBarCodeValue) 232 { 233 g.DrawString(_barCodeValue, BarCodeValueFont, new SolidBrush(Color.Black), 234 XCenter((int)_sizeBarCodeString.Width, barCodeWidth), 235 vPos + (int)_sizeBarCodeValue.Height); 236 } 237 //else 238 //{ 239 // //if (!string.IsNullOrEmpty(_additionalInfo)) 240 // //{ 241 // // g.DrawString(_additionalInfo, AdditionalInfoFont, new SolidBrush(Color.Black), 242 // // //XCenter((int)_sizeAdditionalInfo.Width, barCodeWidth), 243 // // vPos + (int)_sizeBarCodeValue.Height); 244 // //} 245 //} 246 } 247 Stream ms = new MemoryStream(); 248 bmp.Save(ms, imageFormat); 249 return ms; 250 } 251 } 252 #endregion 253 private static int XCenter(int subWidth, int globalWidth) 254 { 255 return (globalWidth - subWidth) / 2; 256 } 257 }
这是从网上找的一段代码,感觉挺高大上,而且比我之前写的简易的调整起来方便 简易代码也张贴一下,但是我不建议用它,因为个人感觉不方便没上边的那段代码好用,因为上边的还可以在web段进行调用,专门有web段调用的方法。我写的这个可以直接在程序中使用,不需要重新创建类。
1 Bitmap b=new Bitmap(200,200); 2 Graphics g = Graphics.FromImage(b); 3 Font font = new Font("Code39AzaleaRegular2", 32); 4 g.DrawString("123456", font, Brushes.Black, new PointF(100,100)); 5 pictureBox1.BackgroundImage = b; 6 pictureBox1.BackgroundImageLayout = ImageLayout.Zoom
对了说到web端调用生成条形码方法,顺便张贴一下web调用的方法:
// 新建一个.aspx文件 protected void Page_Load(object sender, EventArgs e) { Code39 code39 = new Code39(); code39.BarCodeValue = "LDSO-001"; code39.BarCodeFontSzie = 60; // code39.Label = "39码,底部显示码值"; code39.ShowBarCodeValue = true; Response.Write(code39.CreateWebForm(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif)); code39 = null; }
生成条形码按钮的click事件代码如下:
1 // 获取文本框内容 2 string barCode = tb_barcode.Text; 3 4 Code39 code39 = new Code39(); 5 6 code39.BarCodeValue = barCode; 7 8 code39.BarCodeFontSzie = 10; 9 10 // code39.Label = barCode; 11 code39.ShowBarCodeValue = true; 12 // 将生成的条形码存放到picturebox控件的image中 13 pic_show.Image = Image.FromStream(code39.CreateWinForm(System.Drawing.Imaging.ImageFormat.Gif));
此时当我们运行程序,并输入正规生成条形码的字段(具体要求请参考度娘所说的),点击生成条形码按钮(之前图片是确定按钮,怕误导大家所以就在粘贴图片时候又更改了名字)时候我们就可以看到这样的情形,如图所示:
看到这一步的时候我就觉得很叼了,然后就是保存图片功能了,保存图片时候就是大神们常常强调的要注重客户体验,所以我们需要让图片保存时候可以让用户进行选择存放位置,代码如下:
1 if (pic_show.Image != null) 2 { 3 // 点击保存时候弹出本地窗口进行图片保存 4 5 SaveFileDialog sfd = new SaveFileDialog(); 6 // 设置文件数据类型 7 sfd.Filter = "数据保存文件(*.jpg)|*.jpg|数据保存文件(*.png)|*.png|数据保存文件(*.bmp)|*.bmp"; 8 // 设置默认文件类型顺序 9 sfd.FilterIndex = 1; 10 11 // 保存对话框是否记忆上一次打开的路径 12 sfd.RestoreDirectory = true; 13 // 14 if (sfd.ShowDialog() == DialogResult.OK) 15 { 16 string localFilePath = sfd.FileName.ToString(); //获得文件路径 17 18 string fileNameExt = localFilePath.Substring(localFilePath.LastIndexOf("//") + 1); //获取文件名,不带路径 19 20 Bitmap bmp = new Bitmap(pic_show.Image); 21 // 保存文件到指定流 22 bmp.Save(localFilePath); 23 24 25 } 26 }
相信上边的代码基本上不用有过多的解释,已经那么多注释了,另外我真心需要强调一下注释,哎。。。被这家新公司弄的心好累,那么大的项目里边居然只有寥寥无几的注释,而且写这个项目的大神已经离职了。。。心中策马奔腾。。。。直接上图,