使用 Google 的 Web API 創建二維碼
介紹
在這篇文章里我將會介紹一個簡單的方法(使用內部的標準空間)用來創建二維碼(QR Code), 記錄關于UserControl的一切用以備查。有許多的庫幫助我們做類似的操作,但是這次我要使用谷歌圖表( Google Charts) (https://developers.google.com/chart/),同時還有System.Net和 System.IO命名空間。
背景
谷歌圖表(Google Charts)可以通過POST被查詢請求(細節看這里: https://developers.google.com/chart/image/docs/post_requests?csw=1),因此,我們必須: a)查詢遠程服務器,尤其是POST的參數(稍后敘述), b)獲取服務器的應答 (一張PNG圖片), c) 使用它對我們而言,就是把它(圖片)繪成我們想要的樣子。
因此, 在 Visual Studio中打開一個工程, 之后添加一個新的用戶控件(User Control)。 把 BorderStyle屬性設置成Fixed3D, 把 DoubleBuffered 設成 True (當控件自己刷新時,避免閃爍)。
使用代碼
我們將要查詢的標準URL如下:http://chart.googleapis.com/chart?chs={WIDTH}x{HEIGHT}&cht=qr&chl={DATA} (大括號里的參數將由實際的參數代替)。chs 由特定的二維碼決定 (width x height) ,chl 包含條形碼所表示的數據。與條形碼大小相關的參數很容易從我們的控制屬性上得出(標準的控制自然是有寬和高的),但是我們還要新建一個變量來存儲一個定長的文本,即表示我們的二維碼所展示的數據。
在UserControl中,我們將標準URI定義為一個常量,定義Data Property以及一個用來存儲本地上下文數據的內部變量:
Const _GOOGLE_URL As String = "http://chart.googleapis.com/chart?chs= [This link is external to TechNet Wiki. It will open in a new window.] {WIDTH}x{HEIGHT}&cht=qr&chl={DATA}" Dim _DATA As String = String.Empty Property Data As String Get Return _DATA End Get Set(value As String) _DATA = value End Set End Property
當我們使用Control時,Data Property在代碼視圖和設計視圖里都是可用的:
現在可以用請求參數來構造一個網址URI,這需要在頁面請求之前通過編碼的方式將數據組裝。要確保沒有特別的字符來干擾我們的查詢。我編寫了一個私有方法來完成這個任務。調用它可以得到一個參數編碼的URI(多虧有WebUtility.UrlEncode函數)。
Private Function getQRURI() As String Dim _qrAddr As String = _GOOGLE_URL.Replace("{WIDTH}", Me.Width.ToString).Replace("{HEIGHT}", Me.Height.ToString) _qrAddr = _qrAddr.Replace("{DATA}", WebUtility.UrlEncode(_DATA)) Return _qrAddr End Function
一旦有數據參數需要被包含,將用我們的尺寸替換掉代碼中的兩個參數{WIDTH}和{HEIGHT}(有關WebUtility.UrlEncode,請看 這里。
現在可以從遠程服務器獲取二維碼圖片了,因為我們已經在服務器上利用QRCode控件產生好二維碼圖片緩存等待您的請求。由于想直接用標準OnPaint繪制方法(可以更好使用PaintEventArgs),我將進行重載,添加我自己的代碼:
Protected Overrides Sub OnPaint(e As PaintEventArgs) MyBase.OnPaint(e) If _DATA Is Nothing Then Exit Sub Dim client As New WebClient() Dim bytes() As Byte = client.DownloadData(getQRURI()) client.Dispose() Dim memStream As New IO.MemoryStream(bytes) Dim bmp As Bitmap = Bitmap.FromStream(memStream) memStream.Dispose() e.Graphics.DrawImage(bmp, 0, 0) End Sub
OnPaints調用標準的繪制操作。下一步,如果有數據請求,我們會進行檢查(另外存在方法),我們用一個新的WebClient實例來處理遠程請求。通過格式化URI方法處理過的下載數據的調用,我們填充一個bytes數組,進而構建一個諸如PNG格式的QR Code二維碼圖片
圖片類型的變量可以通過讀取流的方式進行初始化(就像我們打開本地的一張圖片,會有一份本地流的副本)。既然在內存中我們有自己的字節,我們可以聲明一個基于數組的MemoryStream,并且使用它作為位圖的源。在這一點上,為了實現完美的工作位圖,我們可以利用變量 e,其中的OnPaint事件可以訪問自己,以此在我們控制的位置[0;0]繪制圖像。
編譯我們的項目后,QRBox將出現在工具箱里,準備在Form上使用。
使用它非常簡單,只需要設置它的數據和屬性,還有控制刷新的回調。
接下來的簡單Form例子會展示它是如何工作的。我已經向我的Form中添加了QrBox,一個標準的TextBox和Button。
當用戶按下“制作”按鈕時,我們將會讀到一段TextBox文本,并將其傳送到QrBox Data Property中,并且觸發刷新方法。為了開始針對谷歌Charts的遠程查詢,按按鈕產生的代碼將會簡單如下:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click QrBox1.Data = TextBox1.Text QrBox1.Refresh() End Sub
UserControl的完整代碼
QrBox UserControl的完整代碼如下:
Imports System.Net Public Class QRBox Const _GOOGLE_URL As String = "http://chart.googleapis.com/chart?chs={WIDTH}x{HEIGHT}&cht=qr&chl={DATA}" Dim _DATA As String = String.Empty Property Data As String Get Return _DATA End Get Set(value As String) _DATA = value End Set End Property Private Function getQRURI() As String Dim _qrAddr As String = _GOOGLE_URL.Replace("{WIDTH}", Me.Width.ToString).Replace("{HEIGHT}", Me.Height.ToString) _qrAddr = _qrAddr.Replace("{DATA}", WebUtility.UrlEncode(_DATA)) Return _qrAddr End Function Protected Overrides Sub OnPaint(e As PaintEventArgs) MyBase.OnPaint(e) If _DATA Is Nothing Then Exit Sub Dim client As New WebClient() Dim bytes() As Byte = client.DownloadData(getQRURI()) client.Dispose() Dim memStream As New IO.MemoryStream(bytes) Dim bmp As Bitmap = Bitmap.FromStream(memStream) memStream.Dispose() e.Graphics.DrawImage(bmp, 0, 0) End Sub Public Sub New() InitializeComponent() End Sub End Class
我希望本文對你的項目有用。
祝你編碼愉快,工作愉快!