最近在看些条形码方面相关的资料,而如果只是看的话,效果似乎并不怎么好,所以决定动手做点Demo,以增强对相关知识的记忆。
这里是一个我编写的使用WPF生成Code 39的例子,Code 39的编码很简单,故而第一次先用它做为尝试。
标准的Code 39只支持43个字符,0~9,A~Z,-,.,$, /, +, %以及空格。除此之外,*用于起始和终止符号。而通过使用两个编码符的扩展,则可以支持所有的Acsii码字符。相关知识可以在维基百科上找到。
由于是WPF,Demo分为两个文件,xaml文件包含界面布局相关的代码:
1 <Window x:Class="Code39Demo.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition></RowDefinition> 8 <RowDefinition></RowDefinition> 9 </Grid.RowDefinitions> 10 <TextBox Name="Textbox1" VerticalContentAlignment="Center" TextChanged="Textbox1_TextChanged"></TextBox> 11 <Canvas Name="Canvas1" Grid.Row="1"></Canvas> 12 </Grid> 13 </Window>
xaml.cs文件是具体的实现,主要功能是在文本框内容改变的时候动态构成Code 39条形码:
1 using System.Collections.Generic; 2 using System.Text; 3 using System.Text.RegularExpressions; 4 using System.Windows; 5 using System.Windows.Controls; 6 using System.Windows.Media; 7 using System.Windows.Shapes; 8 9 namespace Code39Demo 10 { 11 /// <summary> 12 /// Interaction logic for MainWindow.xaml 13 /// </summary> 14 public partial class MainWindow : Window 15 { 16 public MainWindow() 17 { 18 InitializeComponent(); 19 } 20 21 private void Window_Loaded(object sender, RoutedEventArgs e) 22 { 23 Textbox1.Focus(); 24 } 25 26 private void Textbox1_TextChanged(object sender, TextChangedEventArgs e) 27 { 28 Canvas1.Children.Clear(); 29 30 TextBox textBox = e.Source as TextBox; 31 if (textBox != null) 32 { 33 string content = textBox.Text; 34 if (string.IsNullOrEmpty(content)) 35 { 36 textBox.BorderBrush = null; 37 return; 38 } 39 40 string code = string.Empty; 41 bool result = TryConvertCode(content, out code); 42 if (!result) 43 { 44 textBox.BorderBrush = new SolidColorBrush(Colors.Red); 45 textBox.BorderThickness = new Thickness(2); 46 return; 47 } 48 else 49 { 50 textBox.BorderBrush = null; 51 } 52 53 int thinWidth = 3; 54 int thickWidth = 3 * thinWidth; 55 int currentPos = 10; 56 57 for (int i = 0; i < code.Length; i++) 58 { 59 Rectangle r = new Rectangle(); 60 r.Height = 150; 61 62 Canvas.SetLeft(r, currentPos); 63 64 switch (code[i]) 65 { 66 case 'N': 67 { 68 r.Fill = new SolidColorBrush(Colors.Black); 69 currentPos += thinWidth; 70 r.Width = thinWidth; 71 break; 72 } 73 case 'n': 74 { 75 r.Fill = new SolidColorBrush(Colors.White); 76 currentPos += thinWidth; 77 r.Width = thinWidth; 78 break; 79 } 80 case 'W': 81 { 82 r.Fill = new SolidColorBrush(Colors.Black); 83 currentPos += thickWidth; 84 r.Width = thickWidth; 85 break; 86 } 87 case 'w': 88 { 89 r.Fill = new SolidColorBrush(Colors.White); 90 currentPos += thickWidth; 91 r.Width = thickWidth; 92 break; 93 } 94 } 95 96 Canvas1.Children.Add(r); 97 } 98 } 99 } 100 101 private bool TryConvertCode(string content, out string code) 102 { 103 code = string.Empty; 104 string c = "*" + content + "*"; 105 StringBuilder sb = new StringBuilder(); 106 107 for (int i = 0; i < c.Length; i++) 108 { 109 string value = string.Empty; 110 bool result = _code39Map.TryGetValue(c[i], out value); 111 if (!result) 112 { 113 return false; 114 } 115 116 sb.Append(value); 117 sb.Append('n'); 118 } 119 120 code = sb.Remove(sb.Length - 1, 1).ToString(); 121 122 return true; 123 } 124 125 private static Dictionary<char, string> _code39Map = new Dictionary<char, string>(); 126 127 static MainWindow() 128 { 129 _code39Map['0'] = "NnNwWnWnN"; 130 _code39Map['1'] = "WnNwNnNnW"; 131 _code39Map['2'] = "NnWwNnNnW"; 132 _code39Map['3'] = "WnWwNnNnN"; 133 _code39Map['4'] = "NnNwWnNnW"; 134 _code39Map['5'] = "WnNwWnNnN"; 135 _code39Map['6'] = "NnWwWnNnN"; 136 _code39Map['7'] = "NnNwNnWnW"; 137 _code39Map['8'] = "WnNwNnWnN"; 138 _code39Map['9'] = "NnWwNnWnN"; 139 140 _code39Map['A'] = "WnNnNwNnW"; 141 _code39Map['B'] = "NnWnNwNnW"; 142 _code39Map['C'] = "WnWnNwNnN"; 143 _code39Map['D'] = "NnNnWwNnW"; 144 _code39Map['E'] = "WnNnWwNnN"; 145 _code39Map['F'] = "NnWnWwNnN"; 146 _code39Map['G'] = "NnNnNwWnW"; 147 _code39Map['H'] = "WnNnNwWnN"; 148 _code39Map['I'] = "NnWnNwWnN"; 149 _code39Map['J'] = "NnNnWwWnN"; 150 _code39Map['K'] = "WnNnNnNwW"; 151 _code39Map['L'] = "NnWnNnNwW"; 152 _code39Map['M'] = "WnWnNnNwN"; 153 _code39Map['N'] = "NnNnWnNwW"; 154 _code39Map['O'] = "WnNnWnNwN"; 155 _code39Map['P'] = "NnWnWnNwN"; 156 _code39Map['Q'] = "NnNnNnWwW"; 157 _code39Map['R'] = "WnNnNnWwN"; 158 _code39Map['S'] = "NnWnNnWwN"; 159 _code39Map['T'] = "NnNnWnWwN"; 160 _code39Map['U'] = "WwNnNnNnW"; 161 _code39Map['V'] = "NwWnNnNnW"; 162 _code39Map['W'] = "WwWnNnNnN"; 163 _code39Map['X'] = "NwNnWnNnW"; 164 _code39Map['Y'] = "WwNnWnNnN"; 165 _code39Map['Z'] = "NwWnWnNnN"; 166 167 _code39Map['-'] = "NwNnNnWnW"; 168 _code39Map['.'] = "NwNnNnWnW"; 169 _code39Map[' '] = "NwWnNnWnN"; 170 _code39Map['$'] = "NwNwNwNnN"; 171 _code39Map['/'] = "NwNwNnNwN"; 172 _code39Map['+'] = "NwNnNwNwN"; 173 _code39Map['%'] = "NnNwNwNwN"; 174 175 _code39Map['*'] = "NwNnWnWnN"; 176 } 177 } 178 }
各字符对应编码中,W表示黑色宽条,w表示白色宽条,N表示黑色窄条,n表示白色窄条。需要注意的是,Code 39的相邻字符间需要有一个白色窄条用于分隔。
这个Demo还欠缺Code 39中校验码的处理(通常不需要),如果有需要的话,可以在此基础上补充,相信并不是困难的工作。
原文同步发布于我的个人博客