使用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的左下角,見下圖所示:

        在進行了上述所有修改後,本項目的結帳收款單上就可以打印出用於微信支付的二維碼了。

相關文章
相關標籤/搜索