目录
一、需求
1、批量生成二维码;
2、实时打印日志;
3、实时监测生成进度;
4、可暂停、继续生成;
5、生成的二维码图片保存在本地,并把扫码数据打印在文本文件中;
6、日志与生成的二维码在客户端实时显示;
QR建议:使用ZXing斑马库,GitHub上开源;
二、实现
简单做了一下,有些许小Bug,比较简单,自行解决。
主要代码如下:
1、TCP服务器
XAML代码
<Window x:Class="QrCodeTest.MainWindow"
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:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:QrCodeTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="clr-namespace:QrCodeTest.Models"
xmlns:vm="clr-namespace:QrCodeTest.ViewModels"
Title="MainWindow"
Width="900"
Height="800"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
<ResourceDictionary Source="/QrCodeTest;component/Genery.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Window.DataContext>
<vm:MainWinViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<GroupBox Height="400"
Background="LightSeaGreen"
FontWeight="Black"
Header="二维码显示">
<Grid Margin="3" Background="White">
<Image Source="{Binding ImgSource}" />
</Grid>
</GroupBox>
<StackPanel Grid.Row="1">
<StackPanel>
<ProgressBar Width="150"
Height="150"
Margin="5"
Template="{StaticResource protemp}"
Value="{Binding ProcessValue}" />
<TextBlock HorizontalAlignment="Center"
FontSize="20"
FontWeight="Bold"
Foreground="Black"
Text="生成进度" />
<TextBox Height="40"
Margin="5"
BorderBrush="LightSeaGreen"
BorderThickness="3"
FontSize="20"
FontWeight="Bold"
Text="{Binding Number}" />
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Width="90"
Height="90"
Margin="5"
Background="LightGray"
BorderBrush="LightSeaGreen"
BorderThickness="3"
Command="{Binding GetQrCommand}"
Content="Start"
FontSize="25"
FontWeight="Bold"
Foreground="DarkGreen"
IsEnabled="{Binding StartEnable}" />
<Button Grid.Column="1"
Width="90"
Height="90"
Margin="5"
Background="LightGray"
BorderBrush="LightSeaGreen"
BorderThickness="3"
Command="{Binding StopCommand}"
Content="Stop"
FontSize="25"
FontWeight="Bold"
Foreground="Red" />
<Button Grid.Column="2"
Width="90"
Height="90"
Margin="5"
Background="LightGray"
BorderBrush="LightSeaGreen"
BorderThickness="3"
Command="{Binding ClearLogCommand}"
Content="清空日志"
FontSize="16"
FontWeight="Bold"
Foreground="Blue" />
<Button Grid.Column="3"
Width="90"
Height="90"
Margin="5"
Background="LightGray"
BorderBrush="LightSeaGreen"
BorderThickness="3"
Command="{Binding OpenServerCommand}"
Content="开启服务"
FontSize="16"
FontWeight="Bold"
Foreground="DarkMagenta" />
</Grid>
</StackPanel>
</Grid>
<GroupBox Grid.Column="1"
Background="LightGreen"
FontWeight="Black"
Header="日志">
<ListView Margin="3"
d:ItemsSource="{d:SampleData ItemCount=3}"
ItemsSource="{Binding QrInfos}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<Border Width="NaN"
BorderBrush="Black"
BorderThickness="1">
<TextBlock HorizontalAlignment="Center"
FontSize="15"
Text="Id" />
</Border>
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type model:QrInfo}">
<Border BorderBrush="DarkGreen" BorderThickness="0">
<TextBlock FontSize="15" Text="{Binding Id}" />
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<Border Width="NaN"
BorderBrush="Black"
BorderThickness="1">
<TextBlock HorizontalAlignment="Center"
FontSize="15"
Text="文件名" />
</Border>
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type model:QrInfo}">
<Border BorderBrush="DarkGreen" BorderThickness="0">
<TextBlock FontSize="15" Text="{Binding QrName}" />
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<Border Width="NaN"
BorderBrush="Black"
BorderThickness="1">
<TextBlock HorizontalAlignment="Center"
FontSize="15"
Text="大小(byte)" />
</Border>
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type model:QrInfo}">
<Border BorderBrush="DarkGreen" BorderThickness="0">
<TextBlock FontSize="15" Text="{Binding Size}" />
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<Border Width="NaN"
BorderBrush="Black"
BorderThickness="1">
<TextBlock HorizontalAlignment="Center"
FontSize="15"
Text="最后修改时间" />
</Border>
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type model:QrInfo}">
<Border BorderBrush="DarkGreen" BorderThickness="0">
<TextBlock FontSize="15" Text="{Binding CreateTime}" />
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</GroupBox>
</Grid>
</Window>
C#后台代码
ViewModel
namespace QrCodeTest.ViewModels
{
internal class MainWinViewModel : BindableBase
{
private int flagNum;
private CancellationTokenSource cts;
private StringBuilder sb;
private TcpListener tcpListener;
private TcpClient tcpClient;
private NetworkStream stream;
private double _processValue;
public double ProcessValue
{
get => _processValue;
set => SetProperty(ref _processValue, value);
}
private int _number;
public int Number
{
get => _number;
set => SetProperty(ref _number, value);
}
private bool _startEnable;
public bool StartEnable
{
get => _startEnable;
set => SetProperty(ref _startEnable, value);
}
private ImageSource _imgSource;
public ImageSource ImgSource
{
get => _imgSource;
set => SetProperty(ref _imgSource, value);
}
private ObservableCollection<QrInfo> _qrInfos;
public ObservableCollection<QrInfo> QrInfos
{
get => _qrInfos;
set => SetProperty(ref _qrInfos, value);
}
/// <summary>
/// 开始生成二维码
/// </summary>
public void GetQrCode()
{
if (Number > 0)
{
StartEnable = false;
cts = new CancellationTokenSource();
string savepath = Path.Combine(Directory.GetCurrentDirectory() + @"/MyQr");
if (!Directory.Exists(savepath))
{
Directory.CreateDirectory(savepath);
}
else if (flagNum == 0)
{
Directory.Delete(savepath, true);
Directory.CreateDirectory(savepath);
}
Task.Factory.StartNew(() =>
{
while (!cts.IsCancellationRequested)
{
string content = DateTime.Now.ToString();
Bitmap map = QrCodeServer.GetQrCode(300, 300, content);
sb.AppendLine(content);
File.WriteAllText(Path.Combine(savepath, "QrText"), sb.ToString());
//Bitmap map = QrCodeServer.GetQrCode(300, 300, $"二维码ID:{i}\t生成时间:"+ DateTime.Now.ToString());
Application.Current.Dispatcher.Invoke(() =>
{
ImgSource = Imaging.CreateBitmapSourceFromHBitmap(map.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
Image image = map;
image.Save(Path.Combine(savepath, $"Qr{flagNum + 1}"), ImageFormat.Gif);
FileInfo fileInfo = new FileInfo(Path.Combine(savepath, $"Qr{flagNum + 1}"));
QrInfos.Add(new QrInfo() { Id = flagNum + 1, QrName = fileInfo.Name, CreateTime = fileInfo.LastWriteTime.ToString(), Size = fileInfo.Length });
ProcessValue = (double)(flagNum + 1) / Number;
});
if (tcpListener.Pending() && tcpClient == null)
{
tcpClient = tcpListener.AcceptTcpClient();
stream = tcpClient.GetStream();
}
if (tcpClient != null)
{
byte[] buffer = new byte[1024*6];
int tmp = 0;
var size =Encoding.UTF8.GetBytes( QrInfos[flagNum].Size.ToString());
foreach (var s in size)
{
buffer[tmp] = s;
tmp++;
}
tmp = 5;
var name = Encoding.UTF8.GetBytes(QrInfos[flagNum].QrName);
foreach(var kvp in name )
{
buffer[tmp] = kvp;
tmp++;
}
tmp = 10;
var bytes = Encoding.UTF8.GetBytes( content);
foreach (var item in bytes)
{
buffer[tmp] = item;
tmp++;
}
tmp = 30;
byte[] bytes1=File.ReadAllBytes(Path.Combine(savepath, $"Qr{flagNum + 1}"));
foreach (var item in bytes1)
{
buffer[tmp++]=item;
}
//byte[] bytes1 = Encoding.Default.GetBytes(ImgSource.ToString());
//foreach (var item in bytes1)
//{
// buffer[tmp++] = item;
//}
stream.Write(buffer, 0, buffer.Length);
}
flagNum++;
if (flagNum == Number)
{
StartEnable = true;
cts = null;
sb.Clear();
//File.WriteAllText(Path.Combine(savepath,"QrText"), sb.ToString());
//QrInfos.Clear();
flagNum = 0;
break;
}
Thread.Sleep(1000);
}
}, cts.Token);
/*********单个二维码生成测试
Bitmap map = QrCodeServer.GetQrCode(300, 300, DateTime.Now.ToLongDateString());
ImgSource = Imaging.CreateBitmapSourceFromHBitmap(map.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
Image image = map;
image.Save(Path.Combine(savepath,"Qr1"), ImageFormat.Png);
FileInfo fileInfo = new FileInfo(Path.Combine(savepath, "Qr1"));
QrInfos.Add(new QrInfo() { Id = 1, QrName = fileInfo.Name, CreateTime = fileInfo.LastWriteTime.ToString(), Size =fileInfo.Length });
******************/
}
}
/// <summary>
/// 停止二维码生成
/// </summary>
public void Stop()
{
StartEnable = true;
if (cts != null)
{
cts.Cancel();
cts = null;
}
}
/// <summary>
/// 清空日志
/// </summary>
public void ClearLog()
{
QrInfos.Clear();
}
/// <summary>
/// 开启服务器
/// </summary>
public void OpenServer()
{
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
tcpListener = new TcpListener(iPEndPoint);
tcpListener.Start();
MessageBox.Show("服务器已开启!");
}
public DelegateCommand GetQrCommand { get; set; }
public DelegateCommand StopCommand { get; set; }
public DelegateCommand ClearLogCommand { get; set; }
public DelegateCommand OpenServerCommand { get; set; }
public MainWinViewModel()
{
QrInfos = new ObservableCollection<QrInfo>();
sb= new StringBuilder();
StartEnable = true;
flagNum = 0;
Number = 0;
ProcessValue = 0;
GetQrCommand = new DelegateCommand(GetQrCode);
StopCommand = new DelegateCommand(Stop);
ClearLogCommand = new DelegateCommand(ClearLog);
OpenServerCommand = new DelegateCommand(OpenServer);
}
}
}
QR生成
public static Bitmap GetQrCode(int width,int height,string content)
{
BarcodeWriter writer = new BarcodeWriter();
writer.Format = BarcodeFormat.QR_CODE;
QrCodeEncodingOptions options = new QrCodeEncodingOptions();
options.DisableECI = true;
options.CharacterSet = "UTF-8";//设置内容编码
options.Width = width;//设置二维码长宽
options.Height = height;
options.Margin = 1;//设置二维码边距
writer.Options = options;
Bitmap bitmap = writer.Write(content);
return bitmap;
}
2、TCP客户端
XAML前台
<Window x:Class="QrCodeClient.MainWindow"
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:local="clr-namespace:QrCodeClient"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:QrCodeClient.ViewModels"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.DataContext>
<vm:MainWinViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<GroupBox Height="300"
Background="Gray"
FontSize="20"
FontWeight="Black"
Header="Qr显示">
<Grid Margin="10" Background="White">
<Image Source="{Binding ImgSource}" />
</Grid>
</GroupBox>
<Button Grid.Row="1"
Width="150"
Height="80"
BorderBrush="LightSeaGreen"
BorderThickness="5"
Command="{Binding ConnectCommand}"
Content="连接服务器"
FontSize="20"
FontWeight="Black" />
</Grid>
<GroupBox Grid.Column="1"
Background="LightGreen"
FontSize="20"
FontWeight="Black"
Header="Qr日志">
<ListView Margin="10"
d:ItemsSource="{d:SampleData}"
FontSize="15"
ItemsSource="{Binding QrInfos}">
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Background" Value="LightSeaGreen" />
<Setter Property="FontSize" Value="20" />
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn Width="70" Header="Qr">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:QrInfo}">
<TextBlock Text="{Binding QrName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Size">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:QrInfo}">
<TextBlock Text="{Binding Size}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="250" Header="扫码内容">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:QrInfo}">
<TextBlock Text="{Binding Content}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!--<GridViewColumn Header="Qr" DisplayMemberBinding="{Binding QrInfo.QrName}"/>
<GridViewColumn Header="大小(byte)" DisplayMemberBinding="{Binding QrInfo.Size}"/>
<GridViewColumn Header="内容" DisplayMemberBinding="{Binding QrInfo.Content}"/>-->
</GridView>
</ListView.View>
</ListView>
</GroupBox>
</Grid>
</Window>
C#后台代码
namespace QrCodeClient.ViewModels
{
internal class MainWinViewModel : BindableBase
{
private TcpClient tcpClient;
private NetworkStream stream;
public ObservableCollection<QrInfo> QrInfos { get; set; }
private ImageSource _imgSource;
public ImageSource ImgSource
{
get => _imgSource;
set => SetProperty(ref _imgSource, value);
}
public DelegateCommand ConnectCommand { get; set; }
public void ConnectServer()
{
try
{
tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Parse("127.0.0.1"), 8888);
stream = tcpClient.GetStream();
}
catch (Exception)
{
MessageBox.Show("连接失败,请重新尝试。。。", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
MessageBox.Show("连接成功,开始接受数据。。。", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
byte[] buffer = new byte[1024 * 6];
Task.Run(() =>
{
while (true)
{
if (stream.DataAvailable)
{
Array.Clear(buffer, 0, buffer.Length);
stream.Read(buffer, 0, buffer.Length);
QrInfo info = new QrInfo();
byte[] bytes1 = buffer.Take(5).ToArray();
var size = Encoding.UTF8.GetString(bytes1);
info.Size = Convert.ToInt32(size);
byte[] bytes2 = buffer.Skip(5).Take(5).ToArray();
var qrname = Encoding.Default.GetString(bytes2);
info.QrName = qrname;
byte[] bytes3 = buffer.Skip(10).Take(20).ToArray();
var qrcontent = Encoding.Default.GetString(bytes3);
info.Content = qrcontent;
byte[] bytes4 = buffer.Skip(30).ToArray();
MemoryStream memoryStream = new MemoryStream(bytes4);
var bitmap = new Bitmap(memoryStream);
//var img = System.Drawing.Image.FromStream(memoryStream);
Application.Current.Dispatcher.Invoke(() =>
{
ImgSource = Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
QrInfos.Add(info);
});
}
Thread.Sleep(1000);
}
});
}
public MainWinViewModel()
{
QrInfos = new ObservableCollection<QrInfo>();
ConnectCommand = new DelegateCommand(ConnectServer);
}
}
}
3、成果视频
QRCodeTest