继上次做了第一个随机生成验证码的案例后,界面设计更加方便而且灵活,代码完全可以实现every想要的界面。
本文主要是利用ZXing.Net实现生成二维码和解码的功能,以及文件打开、保存的小功能,先上效果图:
目录
1.界面设计
2.代码实现
(1)安装ZXing.Net
(2)创建QRCodeCreator函数
(3)创建DecodeQRCode函数
(4)图像格式的转换
生成二维码时
打开文件时
保存文件时
3.结果
引申:
IntPtr的使用
主要用到的控件:
menu:最简单的菜单功能,包括File(Open、Save as)、Operation(Create、Decode)功能;
Image:用于显示二维码图像;
Textbox:用于输入和显示二维码的内容;
Button:通过点击menu中的Operation来切换该button的功能,同时button会显示Create/Decode字样。
xaml中的代码如下:
首先介绍一下ZXing.Net。ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口,而ZXing.Net是ZXing的端口之一。可以利用ZXing.Net生成二维码、条形码等。
安装方法:工具->NuGet包管理器->管理解决方案的NuGet程序包->搜索“ZXing.Net”,安装第一个。
利用BarcodeWriter类,构建写码器,设置一些参数,再生成二维码,返回Bitmap类型。
private Bitmap QRCodeCreator(string strMessage, int width, int height)
{
Bitmap result = null;
try
{
//Create BarcodeWriter
BarcodeWriter barCodeWriter = new BarcodeWriter();
barCodeWriter.Format = BarcodeFormat.QR_CODE;
barCodeWriter.Options.Hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
barCodeWriter.Options.Hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H);
barCodeWriter.Options.Height = height;//二维码图片高度
barCodeWriter.Options.Width = width;//二维码图片宽度
barCodeWriter.Options.Margin = 0;
//Create QR code
//使用BitMatrix来描述一个二维码,在其内部存储一个看似boolean值的矩阵数组
//很好地抽象了二维码
ZXing.Common.BitMatrix bm = barCodeWriter.Encode(strMessage);
result = barCodeWriter.Write(bm);
}
catch
{
//
}
return result;
}
利用BarcodeReader类进行解码,返回string类型。
private string DecodeQRCode(Bitmap barcodeBitmap)
{
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
Result result = reader.Decode(barcodeBitmap);
return result.Text;
}
本文中涉及有两个地方需要进行格式转换,
将Bitmap转为ImageSource,结果显示在Image控件中;(上一篇中也提到这样的转换)
private void Button_Click(object sender, RoutedEventArgs e)
{
if (mode == 1)//CreateQR
{
string str = textbox.Text;
bitmap = QRCodeCreator(str, (int)(image.Width), (int)(image.Height));
image.Source = ChangeBitmapToImageSource(bitmap);
}
else if (mode == 2) //DecodeQR
{
textbox.Text = DecodeQRCode(bitmap);
}
}
public static ImageSource ChangeBitmapToImageSource(Bitmap bitmap)
{
IntPtr hBitmap = bitmap.GetHbitmap();
try
{
ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
//Need to release the hBitmap in time, otherwise the memory will fill up quickly.
DeleteObject(hBitmap);
return wpfBitmap;
}
catch
{
DeleteObject(hBitmap);
return null;
}
}
bmp、BitmapImage、BitmapSource、Bitmap之间的转换;
private void Open_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "bmp,jpg,png|*.bmp;*.jpg;*.png";
DialogResult dr = ofd.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
image.Source = new BitmapImage(new Uri(ofd.FileName));
//BitmapSource to Bitmap
BitmapSource bs = (BitmapSource)image.Source;
Bitmap bitmap1 = new Bitmap((int)(image.Width), (int)(image.Height), System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
System.Drawing.Imaging.BitmapData data = bitmap1.LockBits(
new System.Drawing.Rectangle(System.Drawing.Point.Empty, bitmap1.Size),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
bs.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
bitmap = (Bitmap)bitmap1.Clone();
}
else
{
System.Windows.Forms.MessageBox.Show("There is no image.");
}
}
Bitmap转为bmp。
private void Saveas_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "bmp|*.bmp";
DialogResult sdr = sfd.ShowDialog();
if (sdr == System.Windows.Forms.DialogResult.OK)
{
bitmap.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
System.Windows.Forms.MessageBox.Show("Succeed to save file.");
}
else
{
System.Windows.Forms.MessageBox.Show("Fail to save file.");
}
}
如文章最开始的效果。
本次案例和上次的案例中,均用到IntPtr,C#中可以使用IntPtr访问内存,记得及时释放,以免内存溢出。
可以参考:https://www.cnblogs.com/Vennet/p/3897281.html
新手程序媛正在努力从学习中总结、从总结中学习,如有错误或者不同见解,请指正,thx~