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

1 篇文章 1 订阅

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

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

                             

目录

1.界面设计

2.代码实现

(1)安装ZXing.Net

(2)创建QRCodeCreator函数

(3)创建DecodeQRCode函数

(4)图像格式的转换

生成二维码时

打开文件时

保存文件时

3.结果

引申:

IntPtr的使用


 


1.界面设计

                       

主要用到的控件:

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

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

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

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

xaml中的代码如下:

<Window x:Class="WpfApp_QRcode.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp_QRcode"
        mc:Ignorable="d"
        Title="QRCoder" Height="450" Width="609.5">
    <Grid HorizontalAlignment="Left" Width="604">
        <Border BorderBrush="Black" BorderThickness="1" Height="300" HorizontalAlignment="Left" Margin="127,39,0,0" VerticalAlignment="Top" Width="300">
            <Image x:Name="image" HorizontalAlignment="Left" Height="300" Margin="-1" VerticalAlignment="Top" Width="300" />
        </Border>
        <TextBox x:Name="textbox" HorizontalAlignment="Left" Height="25" Margin="127,364,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="300"/>
        <Button x:Name="btn" Content="button" HorizontalAlignment="Left" Margin="450,364,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <Menu Name="menu" HorizontalAlignment="Left" Height="24" VerticalAlignment="Top" Width="789" RenderTransformOrigin="0.5,0.5">
            <Menu.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform Angle="-0.362"/>
                    <TranslateTransform/>
                </TransformGroup>
            </Menu.RenderTransform>
            <MenuItem Header="File" FontSize="14">
                <MenuItem Header="Open" Click="Open_Click"/>
                <MenuItem Header="Save as" Click="Saveas_Click"/>
            </MenuItem>
            <MenuItem Header="Operation" FontSize="14">
                <MenuItem Header="CreateQR" Click="CreateQR_Click"/>
                <MenuItem Header="DecodeQR" Click="DecodeQR_Click"/>
            </MenuItem>
        </Menu>
    </Grid>
</Window>

2.代码实现

(1)安装ZXing.Net

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

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

                                 

(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~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值