我的WPF学习案例(二):二维码的生成、解码

继上次做了第一个随机生成验证码的案例后,界面设计更加方便而且灵活,代码完全可以实现every想要的界面。

本文主要是利用ZXing.Net实现生成二维码解码的功能,以及文件打开、保存的小功能,先上效果图:

                             我的WPF学习案例(二):二维码的生成、解码_第1张图片

目录

1.界面设计

2.代码实现

(1)安装ZXing.Net

(2)创建QRCodeCreator函数

(3)创建DecodeQRCode函数

(4)图像格式的转换

生成二维码时

打开文件时

保存文件时

3.结果

引申:

IntPtr的使用


 


1.界面设计

                       我的WPF学习案例(二):二维码的生成、解码_第2张图片

主要用到的控件:

menu:最简单的菜单功能,包括File(Open、Save as)、Operation(Create、Decode)功能;

Image:用于显示二维码图像;

Textbox:用于输入和显示二维码的内容;

Button:通过点击menu中的Operation来切换该button的功能,同时button会显示Create/Decode字样。

xaml中的代码如下:


    
        
            
        
        
        

2.代码实现

(1)安装ZXing.Net

首先介绍一下ZXing.Net。ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口,而ZXing.Net是ZXing的端口之一。可以利用ZXing.Net生成二维码、条形码等。

安装方法:工具->NuGet包管理器->管理解决方案的NuGet程序包->搜索“ZXing.Net”,安装第一个。

                                 我的WPF学习案例(二):二维码的生成、解码_第3张图片

(2)创建QRCodeCreator函数

利用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;
        }

(3)创建DecodeQRCode函数

利用BarcodeReader类进行解码,返回string类型。

        private string DecodeQRCode(Bitmap barcodeBitmap)
        {
            BarcodeReader reader = new BarcodeReader();
            reader.Options.CharacterSet = "UTF-8";
            Result result = reader.Decode(barcodeBitmap);
            return result.Text;
        }

(4)图像格式的转换

本文中涉及有两个地方需要进行格式转换,

  • 生成二维码时

将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.");
            }
        }

3.结果

如文章最开始的效果。

 

引申:

IntPtr的使用

本次案例和上次的案例中,均用到IntPtr,C#中可以使用IntPtr访问内存,记得及时释放,以免内存溢出。

可以参考:https://www.cnblogs.com/Vennet/p/3897281.html

 

新手程序媛正在努力从学习中总结、从总结中学习,如有错误或者不同见解,请指正,thx~

你可能感兴趣的:(WPF,C#)