silverlight4.0之条码循环打印
第一步将所需条码代码从网上下下来(网上好多),就code39举例:
BarCode.cs文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Collections.Generic;
using System.Text;
namespace EamManager.BarCode
{
public class Barcodes
{
public enum YesNoEnum
{
Yes,
No
}
public enum BarcodeEnum
{
Code39
}
public string Data
{
get
{
return data;
}
set
{
data = value;
}
}
private string data;
public BarcodeEnum BarcodeType
{
get
{
return barcodeType;
}
set
{
barcodeType = value;
}
}
private BarcodeEnum barcodeType;
public YesNoEnum CheckDigit
{
get
{
return checkDigit;
}
set
{
checkDigit = value;
}
}
private YesNoEnum checkDigit;
public string HumanText
{
get
{
return humanText;
}
set
{
humanText = value;
}
}
private string humanText;
public string EncodedData
{
get
{
return encodedData;
}
set
{
encodedData = value;
}
}
private string encodedData;
public void encode()
{
int check = 0;
if( checkDigit == Barcodes.YesNoEnum.Yes )
check = 1;
if( barcodeType == BarcodeEnum.Code39 )
{
Code39 barcode = new Code39();
encodedData = barcode.encode( data, check );
humanText = barcode.getHumanText();
}
}
}
}
Code39.cs文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Collections.Generic;
using System.Text;
namespace EamManager.BarCode
{
public class Code39
{
//w - wide
//t - thin
//Start the drawing with black, white, black, white......
public string encode( string data, int chk )
{
string fontOutput = mcode( data, chk );
string output = "";
string pattern = "";
for( int x = 0; x < fontOutput.Length; x++ )
{
switch( fontOutput[ x ] )
{
case '1':
pattern = "wttwttttwt";
break;
case '2':
pattern = "ttwwttttwt";
break;
case '3':
pattern = "wtwwtttttt";
break;
case '4':
pattern = "tttwwtttwt";
break;
case '5':
pattern = "wttwwttttt";
break;
case '6':
pattern = "ttwwwttttt";
break;
case '7':
pattern = "tttwttwtwt";
break;
case '8':
pattern = "wttwttwttt";
break;
case '9':
pattern = "ttwwttwttt";
break;
case '0':
pattern = "tttwwtwttt";
break;
case 'A':
pattern = "wttttwttwt";
break;
case 'B':
pattern = "ttwttwttwt";
break;
case 'C':
pattern = "wtwttwtttt";
break;
case 'D':
pattern = "ttttwwttwt";
break;
case 'E':
pattern = "wtttwwtttt";
break;
case 'F':
pattern = "ttwtwwtttt";
break;
case 'G':
pattern = "tttttwwtwt";
break;
case 'H':
pattern = "wttttwwttt";
break;
case 'I':
pattern = "ttwttwwttt";
break;
case 'J':
pattern = "ttttwwwttt";
break;
case 'K':
pattern = "wttttttwwt";
break;
case 'L':
pattern = "ttwttttwwt";
break;
case 'M':
pattern = "wtwttttwtt";
break;
case 'N':
pattern = "ttttwttwwt";
break;
case 'O':
pattern = "wtttwttwtt";
break;
case 'P':
pattern = "ttwtwttwtt";
break;
case 'Q':
pattern = "ttttttwwwt";
break;
case 'R':
pattern = "wtttttwwtt";
break;
case 'S':
pattern = "ttwtttwwtt";
break;
case 'T':
pattern = "ttttwtwwtt";
break;
case 'U':
pattern = "wwttttttwt";
break;
case 'V':
pattern = "twwtttttwt";
break;
case 'W':
pattern = "wwwttttttt";
break;
case 'X':
pattern = "twttwtttwt";
break;
case 'Y':
pattern = "wwttwttttt";
break;
case 'Z':
pattern = "twwtwttttt";
break;
case '-':
pattern = "twttttwtwt";
break;
case '.':
pattern = "wwttttwttt";
break;
case ' ':
pattern = "twwtttwttt";
break;
case '*':
pattern = "twttwtwttt";
break;
case '$':
pattern = "twtwtwtttt";
break;
case '/':
pattern = "twtwtttwtt";
break;
case '+':
pattern = "twtttwtwtt";
break;
case '%':
pattern = "tttwtwtwtt";
break;
}
output = output.Insert( output.Length, pattern );
}
return output;
}
private string humanText;
static char[] CODE39MAP = {'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z','-','.',' ','$',
'/','+','%'};
private string mcode( string data, int chk )
{
string cd = "", result = "";
string filtereddata = filterInput( data );
int filteredlength = filtereddata.Length;
if( chk == 1 )
{
if( filteredlength > 254 )
filtereddata = filtereddata.Remove( 254, filteredlength - 254 );
cd = generateCheckDigit( filtereddata );
}
else
{
if( filteredlength > 255 )
filtereddata = filtereddata.Remove( 255, filteredlength - 255 );
}
result = "*" + filtereddata + cd + "*";
humanText = result;
return result;
}
public string getHumanText()
{
return humanText;
}
string generateCheckDigit( string data )
{
int datalength = 0;
int sum = 0;
int result = -1;
string strResult = "";
char barcodechar;
datalength = data.Length;
for( int x = 0; x < datalength; x++ )
{
barcodechar = data[ x ];
sum = sum + getCode39Value( barcodechar );
}
result = sum % 43;
strResult = getCode39Character( result ).ToString();
return strResult;
}
char getCode39Character( int inputdecimal )
{
return CODE39MAP[ inputdecimal ];
}
int getCode39Value( char inputchar )
{
for( int x = 0; x < 43; x++ )
{
if( CODE39MAP[ x ] == inputchar )
return x;
}
return -1;
}
string filterInput( string data )
{
string result = "";
int datalength = data.Length;
for( int x = 0; x < datalength; x++ )
{
char barcodechar = data[ x ];
if( getCode39Value( barcodechar ) != -1 )
result = result.Insert( result.Length, barcodechar.ToString() );
}
return result;
}
}
}
第二部:设计条码显示界面
新建silverlight用户控件具体如下:
Code.xaml文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<UserControl x:Class="EamManager.BarCode.Code"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" IsEnabled="True" BorderThickness="0" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid x:Name="gr">
<Grid x:Name="grdLayoutRoot" Background="White" Width="270" Height="150" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="10"></RowDefinition>
<RowDefinition Height="29" />
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="137"></ColumnDefinition>
<ColumnDefinition Width="113" />
<ColumnDefinition Width="10"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Canvas x:Name="MyCanvas" Width="250" Height="40" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" />
<TextBlock x:Name="MyText" Height="30" Text="1234" Grid.Row="4" Grid.Column="1" TextAlignment="Center" FontSize="13" Margin="0,0,2,0" />
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Grid.ColumnSpan="2" Margin="22,0">
<Image Height="26" Name="image1" Stretch="Fill" VerticalAlignment="Center" Width="28" Source="/EamManager;component/Images/logo1.png" />
<TextBlock Height="26" Name="textBlock1" Text=" xxx学院资产" VerticalAlignment="Center" FontSize="14" />
</StackPanel>
</Grid>
</Grid>
</UserControl>
Code.xaml.cs文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace EamManager.BarCode
{
public partial class Code : UserControl
{
public Code(string codedata)
{
InitializeComponent();
Out_Code(codedata);
}
public void Out_Code(string codedata)
{
//条码输出
Barcodes barcode = new Barcodes();
barcode.BarcodeType = Barcodes.BarcodeEnum.Code39;
barcode.Data = codedata;
barcode.encode();
string encodedData = barcode.EncodedData;
MyText.Text = barcode.HumanText;
int encodedLength = 0;
for (int x = 0; x < encodedData.Length; x++)
{
if (encodedData[x] == 't')
encodedLength++;
else if (encodedData[x] == 'w')
encodedLength = encodedLength + 3;
}
float barWidth = (float)(this.MyCanvas.Width / encodedLength);
if (barWidth < 1)
barWidth = 1;
float thickWidth = barWidth * 3;
double incrementWidth = 0;
int swing = 0;
for (int x = 0; x < encodedData.Length; x++)
{
Brush brush;
if (swing == 0)
brush = new SolidColorBrush(Colors.Black);
else
brush = new SolidColorBrush(Colors.White);
if (encodedData[x] == 't')
{
Rectangle r = new Rectangle();
r.Fill = brush;
r.Width = barWidth;
r.Height = this.MyCanvas.Height;
r.SetValue(Canvas.LeftProperty, incrementWidth);
r.SetValue(Canvas.TopProperty, 0.0);
MyCanvas.Children.Add(r);
incrementWidth = incrementWidth + ((barWidth));
}
else if (encodedData[x] == 'w')
{
Rectangle r = new Rectangle();
r.Fill = brush;
r.Width = 3 * barWidth;
r.Height = this.MyCanvas.Height;
r.SetValue(Canvas.LeftProperty, incrementWidth);
r.SetValue(Canvas.TopProperty, 0.0);
MyCanvas.Children.Add(r);
incrementWidth = incrementWidth + (3 * (barWidth));
}
if (swing == 0)
swing = 1;
else
swing = 0;
}
}
}
}
第三步:封装打印方法BarcodePrint.cs文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void Print(UIElement source, string documentName)
{
var doc = new PrintDocument();
var offsetY = 0d;
var totalHeight = 0d;
var canvas = new Canvas();
canvas.Children.Add(source);
doc.EndPrint += (s, e) =>
{
if (e.Error == null)
{
MessageBox.Show("打印成功");
}
else
{
MessageBox.Show(e.Error.Message);
}
};
doc.PrintPage += (s, e) =>
{
e.PageVisual = canvas;
canvas.Margin = new Thickness(50);
if (totalHeight == 0)
{
totalHeight = source.DesiredSize.Height;
}
Canvas.SetTop(source, -offsetY);
offsetY += e.PrintableArea.Height;
e.HasMorePages = offsetY <= totalHeight;
};
doc.Print(documentName);
}
第四步:准备一个窗体PrintWindow.xaml里面代码如下(其实就是只有一个stackpanel控件就好了):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<controls:ChildWindow x:Class="EamManager.PrintWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<StackPanel x:Name="LayoutRoot" >
</StackPanel>
</controls:ChildWindow>
第五步:使用以上的工作,找到打印事件,在里面写:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
PrintWindow pw = new PrintWindow();
foreach (DeviceInfo item in DG_Result.ItemsSource)
{
BarCode.Code code = new BarCode.Code(item.BarCode);
pw.LayoutRoot.Children.Add(code);
}
//DG_Result是datagrid,这里可是其他数据源集合,DeviceInfo为产品类(自定义),BarCode是DeviceInfo的编号
BarcodePrint.Print(pw, "设备条码");
通过以上步骤就实现了条码循环打印功能。
总结:
所遇问题:
silverlight4.0中printdocument类还不够完善,无法实现多次实例化,也就无法实现多次调用。
silverlight4.0采用安全机制,导致无法调用win32 api打印类(可能通过wcf可以,没试过,不过那样不合理)
解决办法:
将要打印的条码控件封装到usercontrol,然后在打印时将所有的usercontrol放到一个页面,然后控制打印时的页面大小,以便实现循环打印。
其实打印的是一个页面,只不过因为页面太大导致效果如同循环打印一般。
当然这种办法虽然实现此功能但是有很大的限制,比如:打印次数以及性能等。一同期待silverlight5.0的出生吧。