如何在ASP.NET和WPF中显示二维码
[原文发表地址] How to display a QR code in ASP.NET and WPF
[原文发表时间] 2014-01-19
我曾半开玩笑的表示过根本没有一个很好的理由需要使用二维码,但是最近我在和Greg Shackles 一起制作一个小型启动的最小可行产品,并且我们有充分的理由要使用二维码。因为我们要在移动设备,网站以及应用程序间传送数据,而使用二维码真是一种较快捷的方法,也避免了蓝牙配对的混乱状况。
如我所提到的,我们要在ASP.NET的网站上显示二维码,同时也在基于WPF框架实现的windows应用以及基于 Xamarin.框架,用C#实现的iphone 应用程序中也显示二维码。
“ZXing"(斑马线)是一个很好的二维码代码库,对于Java和C#都有相应的接口 。C#/.NET,ZXing.NET是个相当棒的项目程序集,它将适用于多种平台的程序集放在了一起,这些平台包括了.NET 2.0到.NET 4.5、windows RT,Unity3D、 Portable libraries 等等。这个网站有许多例子,虽然我们没有找到一个和ASP.NET或WPF相关的,但是也没关系了,它们也只是生成和显示PNG 的图片。
我从这里获得了ZXing.Net, 仅安装 ZXing.Net包就可以了。
如何在ASP.NET中展示二维码
如果你用ASP.NET MVC生成一个二维码,你将会得到这段代码运行的页面,但是接着你需要决定是否需要利用 HTTP Handler 去生成图像,就像如下方式:
<img src="/path/to/httphandlerthatmakesQRcodepng">
或者你可以像我们一样用不同的方法,在HTML页面
Greg 使用HTML助手输出整个图像标签,包括内嵌的图像,如:
<img src="data:image/gif;base64,iVBORw0KG..." />
我觉得图像以DataURI的方式显示在 HTML 页面中是很有趣的,但却经常被遗忘。如果你给一个一般的web开发者展示,他们会说"噢,是…我知道那些,但从未真正使用过它。"事实上,DATA URI已出现了很长一段时间。在dataurl.net你可以学到更多关于DataURI的内容。
这是在ASP.NET MVC中使用HTML助手生成二维码的代码:
public static class HtmlHelperExtensions
{
public static IHtmlString GenerateRelayQrCode(this HtmlHelper html, string groupName, int height = 250, int width = 250, int margin = 0)
{
var qrValue = "whatever data you want to put in here";
var barcodeWriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new EncodingOptions
{
Height = height,
Width = width,
Margin = margin
}
};
using (var bitmap = barcodeWriter.Write(qrValue))
using (var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Gif);
var img = new TagBuilder("img");
img.MergeAttribute("alt", "your alt tag");
img.Attributes.Add("src", String.Format("data:image/gif;base64,{0}",
Convert.ToBase64String(stream.ToArray())));
return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
}
}
}
简洁又美观。在ZXing.NET内的BarcodeWriter类做了艰辛的工作: 我们不需要将二维码保存到磁盘,因为通过这个助手我们可以内嵌在html页面,而不需要一个单独的调用来获取图像。此外,我们决定将此页面缓存策略适用于内嵌图像,远胜于两次调用。
如何在WPF中展示二维码
注:这段代码可能是错的。我亲爱的读者,很高兴能听到来自你们的建议,因为我可能会漏掉什么或者没有一个清晰的方法可以将System.Drawing.Bitmap 的内容转换为System.Windows.Media.imaging.BitmapImage 。这种首先将图片信息保存到MemoryStream,然后转换为BitmapImage的做法,只是出于我的直觉,但是也需要对cacheoption属性进行设置。虽然它可以正常运行,但它可能不是正确的处理方式 。
如果我找到了较为清晰的方式,我会更新代码的。
请参阅下面的更新:
首先,ZXing.NET库里BarcodeWriter的正确使用方式如下:
var qrcode = new QRCodeWriter();
var qrValue = "your magic here";
var barcodeWriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new EncodingOptions
{
Height = 300,
Width = 300,
Margin = 1
}
};
using (var bitmap = barcodeWriter.Write(qrValue))
using (var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
stream.Seek(0, SeekOrigin.Begin);
bi.StreamSource = stream;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
QRCode.Source = bi; //A WPF Image control
}
然后,将Bitmap写入内存流中进行操作,只不过,我们将二维码放到WPF图像控件的源属性中。
Thomas Levesque建议可以使用System.Windows.Interop的扩展CreateBitmapSourceFromHBitmap(这解释了我为什么找不到System.Windows.Interop)。这种方法感觉也不是很好,因为它需要调用本地的Deleteobject方法,但无论如何,我想这个应该还是可以接受的。它就成了下面所展示的,并且运转正常!
using (var bitmap = barcodeWriter.Write(qrValue))
{
var hbmp = bitmap.GetHbitmap();
try
{
var source = Imaging.CreateBitmapSourceFromHBitmap(hbmp, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
QRCode.Source = source;
}
finally
{
DeleteObject(hbmp);
}
}
Comments
- Anonymous
March 08, 2014
Thank you for this lovely post enjoyed a lot http://crokes.com