使用FastReport打印二維碼


        簡單介紹一下該功能所在的項目背景: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 = 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/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的左下角,見下圖所示:

        在進行了上述全部修改后,本項目的結賬收款單上就能夠打印出用於微信支付的二維碼了。

      

      

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM