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

首先,我们要明确一点:二维码其实就是一张图片。因此和打印条形码不同,打印二维码,只需要使用FastReport中的图片控件就可以了。双击图片控件后,有四种方式可以用于设置图片的数据源,如下图所示:

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

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

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

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

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

        /// <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如下所示:

        /// <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 = , int ImageHeight = , bool savelocal = false)
{
try
{
Dictionary<EncodeHintType, object> ht = new Dictionary<EncodeHintType, object>();
ht.Add(EncodeHintType.MARGIN, );
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[];
point[] = new System.Drawing.Point(, );
point[] = new System.Drawing.Point(ImageWidth - , );
point[] = new System.Drawing.Point(, ImageHeight - );
g.FillRectangle(System.Drawing.Brushes.White, new System.Drawing.Rectangle(, , ImageWidth, ImageHeight));
g.DrawImage(bitmap, point, new System.Drawing.Rectangle(rec[], rec[], rec[], rec[]), GraphicsUnit.Pixel);
argb32bp.SetResolution(, );
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/1c2G39IS

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

这里有一个简单的方法,能够为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的左下角,见下图所示:

在进行了上述全部修改后,本项目的结账收款单上就能够打印出用于微信支付的二维码了。

使用FastReport打印二维码的更多相关文章

  1. 安卓四核PDA手持PDA智能POS机 打印二维码 分享

    很多项目都会用到 类似的要求  移动手持终端 通过程序 可以生成条码或二维码 打印出小票或标签纸 下面直接上代码 希望对大家有点用处 private void print(){ csys.setTex ...

  2. C#调用TSC条码打印机打印二维码

    #region 调用TSC打印机打印 /// <summary> /// 调用TSC打印机打印 /// </summary> /// <param name=" ...

  3. C# TSC打印二维码和条形码

    效果图 开发.使用环境说明 安装TSC_7.3.8_M-3.exe打印机驱动,安装时选择对应的ttp 244 pro 将TSCLIB.dll复制到C:\Windows\system 驱动安装说明 选择 ...

  4. Lodop打印二维码内容长度不同如何大小相同

    利用Loodop打印控件打印二维码的时候,往往传入的数值是变量,有的只有一个数字,有的却一大堆数字和字母,根据内容长度不同,二维码大小也不同,这样如果批量打印二维码标签,传入的数据是不同的,会造成有的 ...

  5. vue项目中批量打印二维码

    前提:项目中要打印的二维码为后台返回,批量选择后,点击打印,先打开二维码预览界面,再执行打印. 以下代码中 codePicList为选中的二维码数组.重点css:page-break-after:al ...

  6. vue常用插件之打印功能、二维码插件、批量打印二维码

    vue实现打印的两种方法 vue实现批量打印二维码 (需安装二维码插件qrcodejs2) 一.vue-print-nb插件 1.安装: npm i vue-print-nb -S 2.全局注册(ma ...

  7. ABAP-BarCode-2-Excel打印二维码

    以前用Excel打印过二维码看板标签,将实现过程备注下. 1.安装控件 安装文件:TBarCodeOffice.exe 2.控件注册 打开Excel,找到[选项] 在打开的界面选择[加载项],在活动应 ...

  8. js 打印二维码

    先简单说一下jquery-qrcode,这个开源的三方库(可以从https://github.com/jeromeetienne/jquery-qrcode 获取), qrcode.js 是实现二维码 ...

  9. 斑马105SLPlus串口打印二维码

    1.根据说明书调试硬件,校准介质还有色带(很重要),我自己搞了好几天才搞明白. 2.设置好参数,比如打印介质连续.非连续,热敏还是热转质 3.打印机上电后悔自动校准,校准成功后就可以直接通过串口打印, ...

随机推荐

  1. ADO.NET存取数据库数据

    步骤: //数据库连接串 string conStr = "......" //创建连接对象 SqlConnection connection = new SqlConnectio ...

  2. 设计模式(十)组合模式(Composite Pattern)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  3. perl 如何匹配ASCII码以及ASCII码转换

    匹配ASCII码:   /[:ascii:]/ ASCII码转换为数字: ord() 数字转换为ASCII码: chr()

  4. 使用Ring Buffer构建高性能的文件写入程序

    最近常收到SOD框架的朋友报告的SOD的SQL日志功能报错:文件句柄丢失.经过分析得知,这些朋友使用SOD框架开发了访问量比较大的系统,由于忘记关闭SQL日志功能所以出现了很高频率的日志写入操作,从而 ...

  5. 浅谈为之奋斗过的Set接口

    Set接口 Set接口存储一组唯一,无序的对象 HashSet 是Set接口常用的实现类 HashSet允许集合元素值为null 操作数据的方法与List类似 Set接口不存在get()方法 set ...

  6. JavaScript 函数表达式

    JavaScript中创建函数主要有两种方法:函数声明和函数表达式.这两种方式都有不同的适用场景.这篇笔记主要关注的是函数表达式的几大特点以及它的使用场景,下面一一描述. 主要特点 可选的函数名称 函 ...

  7. Android系统属性简介

    查看Android源码你会发现,代码中大量存在:SystemProperties.set()/SystemProperties.get():通过这两个接口可以对系统的属性进行读取/设置,顾名思义系统属 ...

  8. iOS 升级HTTPS通过ATS你所要知道的

    由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS中使用HTTPS请求的实现.网上搜索了一些比较有用资料,大家可以参考下 苹果强制升级的 ...

  9. Android 多个listview的实现

    正好,今天项目中需要,先写了个demo,给大家参考参考. 先上图,需要的自己,看看具体的代码实现步骤 大概说一下实现步骤: 1.布局中先用 scrollview 包裹 LinearLayout < ...

  10. iOS开发--弹窗多选、单选框架

    最近刚毕业...因为个毕设,都离职了又得重新找工作了,这是之前自己没事开直播写的一个小框架,后来各种趋于稳定后,简单的封装了下,写了个小demo,这里就不废话了,直接贴地址,也不编辑了,自己复制过去看 ...