在這篇文章裡我將會介紹一個簡單的方法(使用內部的標准空間)用來創建二維碼(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
我希望本文對你的項目有用。
祝你編碼愉快,工作愉快!
英文原文:Create QR Codes with Google Web APIs