使用FastReport打印二维码

        简单介绍一下该功能所在的项目背景:C#语言编写的WPF客户端应用程序,在“结帐”模块中,打印出的收款小票上须要显示一个二维码,服务生拿着小票去找顾客,顾客能够选择现金、银行卡等普通支付方式,也能够直接扫小票上的二维码进行微信支付。用于打印小票的模板使用FastReport制做。结帐功能和收款单打印模板已经在使用,如今只须要在原有模板的基础上进行修改。微信

        首先,咱们要明确一点:二维码其实就是一张图片。所以和打印条形码不一样,打印二维码,只须要使用FastReport中的图片控件就能够了。双击图片控件后,有四种方式能够用于设置图片的数据源,以下图所示:编辑器

                       

        这些方法你们一看就知道怎么用,本项目中咱们使用最下面这张大图中的“数据列”方法,用FastReport数据源中的内容对图片进行设置。微信支付

        以本项目的结帐收款单打印模板为例,实现打印二维码的步骤以下所示:url

一、在程序中获取须要打印的二维码数据,并将数据源传给打印模板spa

        在该项目中,使用DataSet向打印模板传递数据源,使用Dictionary<string, string>向打印模板传递参数。传递的方法这里再也不详述。设计

        为了实现打印二维码这个功能,在传递给打印模板的数据源DataSet中添加了一张用于显示二维码的“微信数据”表,还添加了一个参数“微信二维码”。“微信二维码”参数中保存了这个二维码的地址,若地址为空字符串,说明没有微信二维码,不须要打印。在程序端,调用下面的方法AddQRCodeForPrint为打印模板添加二维码所需的数据。微信二维码图片的url(例:weixin://wxpay/payurl?pr=9BF4WY0)是线上的代码生成的,这里不作介绍。code

        /// <summary>
        /// 向打印模板添加微信二维码
        /// </summary>
        /// <param name="dsPrint">数据源</param>
        /// <param name="objdict">参数</param>
        /// <param name="codeURL">微信二维码图片URL</param>
        public static void AddQRCodeForPrint(DataSet dsPrint, Dictionary<string, string> objdict, String codeURL)
        {
            try
            {
                //添加参数:微信二维码图片URL
                objdict.Add("微信二维码", codeURL);

                //将微信二维码写入数据源
                Bitmap bp = GetQrImage(codeURL);
                MemoryStream ms = new MemoryStream();
                bp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                Byte[] code = ms.ToArray();

                DataTable dt = new DataTable();
                dt.Columns.Add("二维码", typeof(Byte[]));
                DataRow dr = dt.NewRow();
                dr["二维码"] = code;
                dt.Rows.Add(dr);
                dt.TableName = "微信数据";
                dsPrint.Tables.Add(dt);
            }
            catch
            {
                if (objdict != null && !objdict.ContainsKey("微信二维码"))
                    objdict.Add("微信二维码", "");
            }
        }

        这个方法中,用于绘制二维码图形的方法GetQrImage以下所示:orm

        /// <summary>
        /// 绘制二维码
        /// </summary>
        /// <param name="qrstr"></param>
        /// <param name="ImageWidth"></param>
        /// <param name="ImageHeight"></param>
        /// <param name="savelocal"></param>
        /// <returns>返回:二维码</returns>
        private static Bitmap GetQrImage(String qrstr, int ImageWidth = 256, int ImageHeight = 256, bool savelocal = false)
        {
            try
            {
                Dictionary<EncodeHintType, object> ht = new Dictionary<EncodeHintType, object>();
                ht.Add(EncodeHintType.MARGIN, 1);
                BitMatrix matrix = new MultiFormatWriter().encode(qrstr, BarcodeFormat.QR_CODE, ImageWidth, ImageHeight, ht);
                Bitmap bitmap = new BarcodeWriter().Write(matrix); //toBitmap(matrix);
                int[] rec = matrix.getEnclosingRectangle(); //二维码全部的位置及大小  前两位是位置  后两位是大小
                Bitmap argb32bp = new Bitmap(ImageWidth, ImageHeight);
                Graphics g = Graphics.FromImage(argb32bp);
                System.Drawing.Point[] point = new System.Drawing.Point[3];
                point[0] = new System.Drawing.Point(5, 5);
                point[1] = new System.Drawing.Point(ImageWidth - 5, 5);
                point[2] = new System.Drawing.Point(5, ImageHeight - 5);
                g.FillRectangle(System.Drawing.Brushes.White, new System.Drawing.Rectangle(0, 0, ImageWidth, ImageHeight));
                g.DrawImage(bitmap, point, new System.Drawing.Rectangle(rec[0], rec[1], rec[2], rec[3]), GraphicsUnit.Pixel);
                argb32bp.SetResolution(120, 120);
                if (savelocal)
                {
                    String filename = DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".png";
                    bitmap.Save(String.Format(@"{0}\{1}", System.Windows.Forms.Application.StartupPath, filename), System.Drawing.Imaging.ImageFormat.Png);
                }
                bitmap.Dispose();
                return argb32bp;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

       上述方法须要添加的引用:System.Drawing、System.IO,以及一个名为zxing的动态库。(zxing的下载连接:http://pan.baidu.com/s/1c2G39ISblog

二、在上面的方法中,程序端已经实现了向打印模板提供所需的数据,接下来须要修改打印模板,接收这些新添加的数据事件

        这里有一个简单的方法,可以为FastReport的数据源中添加一张表。那就是不直接双击打开打印模板,而是在打印模板的文件上右击,选择打开方式为“记事本”。在记事本中找到<Dictionary></Dictionary>这部分,在里面添加数据源和参数。以本项目的结帐收款单打印模板为例,添加了一张用于显示二维码的表“微信数据”,还添加了一个用于肯定是否须要打印二维码的参数“微信二维码”。

        所以,须要在<Dictionary></Dictionary>中添加以下内容

    <TableDataSource Name="微信数据" ReferenceName="Data.微信数据" DataType="System.Int32" Enabled="true">
      <Column Name="二维码" DataType="System.Byte[]"/>
    </TableDataSource>
    <Parameter Name="微信二维码" DataType="System.String"/>

        保存并关闭打印模板的记事本文件。再双击打开打印模板,此时在FastReport的右侧边栏中,能看到数据源里已经多了一个“微信数据”表,以下图所示:

       这里的“二维码”就是步骤1中代码里绘制出的二维码图形,检查这个字段的属性,须要确保它的DataType是Byte[]型的。而且在下面的“参数”列表中,也能看到多了一个“微信二维码”参数。

       为打印模板新建一个数据区,用于打印二维码。点击“报表”——“设置报表栏”菜单,在打开的窗体中点击“添加“按钮,添加”数据区”。将新添加的数据区重命名为Data_PictureCode。主要步骤以下图所示:

                                                              

       为何要新建一个数据区,而不是在原来的数据区里添加二维码呢?由于当不须要打印二维码,也就是“微信二维码”参数为空时,咱们能够直接把这个数据区隐藏,从而不用在打印出的小票上显示出空白的一大片来,也为客户节省纸张。

       在新添加的数据区中插入图片,以下图所示:

                                             

       双击图片,在图片编辑器的“数据列”中,选择“微信数据”表中的“二维码”。以下图所示:

        最后,设置是否须要显示二维码所在的这个数据区。选择一个必定会打印的数据区,在这个数据区的BeforePrint事件中进行控制。首先为所选的数据区添加事件,在FastReport的右侧边栏中,进入到数据区的事件列表(点击那个闪电形状的按钮),在BeforePrint事件后面的编辑框内双击,便可为该数据区添加一个BeforePrint事件。该事件中的代码在打印数据区前执行,以下图所示:

        在所选数据区的BeforePrint事件中添加以下代码,控制是否显示二维码所在的那个数据区

    private void Data10_BeforePrint(object sender, EventArgs e)
    {
      //获取微信二维码url
      string codeURL=(String)Report.GetParameterValue("微信二维码");
      
      //若微信二维码url为空,则不显示二维码数据区
      if(codeURL=="")
      {
        Data_PictureCode.Visible=false;
      }
    }

        代码和打印模板设计界面的切换按钮,在FastReport的左下角,见下图所示:

        在进行了上述所有修改后,本项目的结帐收款单上就可以打印出用于微信支付的二维码了。

相关文章
相关标签/搜索