使用ThoughtWorks.QRCode组件,该组件是一个免费开源的二维码操作动态链接库,在进行程序编写实现该系统的过程中,应先将ThoughtWorks.QRCode.dll文件通过“添加引用”进行添加,在程序中添加指令集:
using ThoughtWorks.QRCode.Codec;
using ThoughtWorks.QRCode.Codec.Data;
using ThoughtWorks.QRCode.Codec.Util;
通过引用该组件中封装的相应的类来实现二维码的生成和解码。其中封装的QRCodeEncoder为二维码编码类,QRCodeDecoder为二维码解码类,QRCodeBitmapImage为位图图像生成类,该类库具体的源码:
1.ORCodeEncoder:二维码编码类
public enum ENCODE_MODE
{
ALPHA_NUMERIC,
NUMERIC,
BYTE
}
public enum ERROR_CORRECTION
{
L,
M,
Q,
H
}
public virtual Bitmap Encode(string content, Encoding encoding)
{
bool[][] flagArray = this.calQrcode(encoding.GetBytes(content));
SolidBrush brush = new SolidBrush(this.qrCodeBackgroundColor);
Bitmap image = new Bitmap((flagArray.Length * this.qrCodeScale) + 1, (flagArray.Length * this.qrCodeScale) + 1);
Graphics graphics = Graphics.FromImage(image);
graphics.FillRectangle(brush, new Rectangle(0, 0, image.Width, image.Height));
brush.Color = this.qrCodeForegroundColor;
for (int i = 0; i < flagArray.Length; i++)
{
for (int j = 0; j < flagArray.Length; j++)
{
if (flagArray[j][i])
{
graphics.FillRectangle(brush, j * this.qrCodeScale, i * this.qrCodeScale, this.qrCodeScale, this.qrCodeScale);
}
}
}
return image;
}
2.QRCodeDecoder:二维码解码类
public virtual string decode(QRCodeImage qrCodeImage, Encoding encoding)
{
sbyte[] src = this.decodeBytes(qrCodeImage);
byte[] dst = new byte[src.Length];
Buffer.BlockCopy(src, 0, dst, 0, dst.Length);
return encoding.GetString(dst);
}
public virtual sbyte[] decodeBytes(QRCodeImage qrCodeImage)
{
DecodeResult result;
Point[] adjustPoints = this.AdjustPoints;
ArrayList list = ArrayList.Synchronized(new ArrayList(10));
while (this.numTryDecode < adjustPoints.Length)
{
try
{
result = this.decode(qrCodeImage, adjustPoints[this.numTryDecode]);
if (result.CorrectionSucceeded)
{
return result.DecodedBytes;
}
list.Add(result);
canvas.println("Decoding succeeded but could not correct");
canvas.println("all errors. Retrying..");
}
catch (DecodingFailedException exception)
{
if (exception.Message.IndexOf("Finder Pattern") >= 0)
{
throw exception;
}
}
finally
{
this.numTryDecode++;
}
}
if (list.Count == 0)
{
throw new DecodingFailedException("Give up decoding");
}
int num = -1;
int numErrors = 0x7fffffff;
for (int i = 0; i < list.Count; i++)
{
result = (DecodeResult) list[i];
if (result.NumErrors < numErrors)
{
numErrors = result.NumErrors;
num = i;
}
}
canvas.println("All trials need for correct error");
canvas.println("Reporting #" + num + " that,");
canvas.println("corrected minimum errors (" + numErrors + ")");
canvas.println("Decoding finished.");
return ((DecodeResult) list[num]).DecodedBytes;
}
3.QRCodeBitmapImage:位图图像
public class QRCodeBitmapImage : QRCodeImage
{
// Fields
private Bitmap image;
// Methods
public QRCodeBitmapImage(Bitmap image);
public virtual int getPixel(int x, int y);
// Properties
public virtual int Height { get; }
public virtual int Width { get; }
}
public interface QRCodeImage
{
// Methods
int getPixel(int x, int y);
// Properties
int Height { get; }
int Width { get; }
}
采用C#WinForm进行二维码编码和解码系统的实现,详细代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using ThoughtWorks.QRCode.Codec;
using ThoughtWorks.QRCode.Codec.Data;
using ThoughtWorks.QRCode.Codec.Util;
using System.IO;
using ControlExs;
namespace WindowsQRCode11_22
{
public partial class Form1 : Form
{
private const long WM_GETMINMAXINFO = 0x24;
public struct POINTAPI
{
public int x;
public int y;
}
public struct MINMAXINFO
{
public POINTAPI ptReserved;
public POINTAPI ptMaxSize;
public POINTAPI ptMaxPosition;
public POINTAPI ptMinTrackSize;
public POINTAPI ptMaxTrackSize;
}
public Form1()
{
InitializeComponent();
this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
cbVersion.Text = "7";
cbEncoding.Text = "Byte";
cbCorrectionLevel.Text = "M";
txtData.Text = "请输入数据内容...";
cbScale.Text = "5";
btnQRCodeForegroundColor.BackColor = System.Drawing.Color.Black;
btnQRCodeBackgroundColor.BackColor = System.Drawing.Color.White;
}
private void Form1_Load(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Maximized; //最大化窗体
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_GETMINMAXINFO)
{
MINMAXINFO mmi = (MINMAXINFO)m.GetLParam(typeof(MINMAXINFO));
mmi.ptMinTrackSize.x = this.MinimumSize.Width;
mmi.ptMinTrackSize.y = this.MinimumSize.Height;
if (this.MaximumSize.Width != 0 || this.MaximumSize.Height != 0)
{
mmi.ptMaxTrackSize.x = this.MaximumSize.Width;
mmi.ptMaxTrackSize.y = this.MaximumSize.Height;
}
mmi.ptMaxPosition.x = 1;
mmi.ptMaxPosition.y = 1;
System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, m.LParam, true);
}
}
//解决窗体闪烁
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
if (!DesignMode)
{
cp.ExStyle |= (int)WindowStyle.WS_CLIPCHILDREN;
}
return cp;
}
}
//生成二维码
private void button1_Click(object sender, EventArgs e)
{
button8.Visible = true;
string encoding = cbEncoding.Text;
string correctionLever = cbCorrectionLevel.Text;
int version = Convert.ToInt32(cbVersion.Text);
int scale = Convert.ToInt32(cbScale.Text);
string data = txtData.Text.Trim();
if (data == string.Empty)
{
MessageBox.Show("请输入数据!","警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (data == "请输入数据内容...")
{
DialogResult dr = MessageBox.Show("您确定输入的数据内容为:“请输入数据内容...”吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (dr == DialogResult.Cancel)
{
txtData.Text = "";
return;
}
else
{
txtData.Text = "请输入数据内容...";
}
}
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();//创建一个对象
//设置编码模式
//当设定目标图片尺寸小于生成的尺寸时,逐步减小方格尺寸
//二维码编码(Byte、AlphaNumeric、Numeric)
/*byte模式,可以支持汉字、英文字母、数字、特殊符号等
Alphanumeric为混合模式,支持的二维码内容:英文大写字母、数字、9个特殊符号,英文小写字母识别为0
Numeric:二维码内容为纯数字
1) numeric data (digits 0 - 9);
2) alphanumeric data (digits 0 - 9; upper case letters A -Z; nine other characters: space, $ % * + - . / : );*/
switch (encoding)
{
case "Byte":
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
break;
case "AlphaNumeric":
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC;
break;
case "Numeric":
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.NUMERIC;
break;
}
#region//设置编码测量度:值越大生成的二维码图片像素越高
//二维码尺寸(Version为0时,1:26x26,每加1宽和高各加25
#endregion
qrCodeEncoder.QRCodeScale = scale;
#region//设置编码版本
//二维码密集度0 - 40
/*二维码一共有40个尺寸。官方叫版本Version。
Version 1是21 x 21的矩阵
Version 2是 25 x 25的矩阵
Version 3是29的尺寸
每增加一个version,就会增加4的尺寸
(V-1)*4 + 21(V是版本号)
最高Version 40,(40-1)*4+21 = 177,所以最高是177 x 177 的正方形
There are forty sizes of QR Code symbol referred to as Version 1, Version 2 ... Version 40. Version 1 measures 21
modules 21 modules, Version 2 measures 25 modules 25 modules and so on increasing in steps of 4 modules
per side up to Version 40 which measures 177 modules 177 modules. Figures 3 to 8 illustrate the structure of
Versions 1, 2, 6, 7, 14, 21 and 40.*/
#endregion
qrCodeEncoder.QRCodeVersion = version;
#region//设置编码错误纠正
//二维码纠错能力(L:7% M:15% Q:25% H:30%)
//L->H:修正的错误增加,对应二维码里包含的错误校验信息增加,相对的图形内容也会越来越密集。
#endregion
if (correctionLever == "L")//L水平7%的字码可被修正
{
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
}
else if (correctionLever == "M")//M水平15%的字码可被修正
{
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
}
else if (correctionLever == "Q")//Q水平25%的字码可被修正
{
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.Q;
}
else if (correctionLever == "H")//H水平30%的字码可被修正
{
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
}
qrCodeEncoder.QRCodeForegroundColor = btnQRCodeForegroundColor.BackColor;//设置二维码前景色
qrCodeEncoder.QRCodeBackgroundColor = btnQRCodeBackgroundColor.BackColor;//设置二维码背景色
Image image = qrCodeEncoder.Encode(data, Encoding.UTF8);//生成二维码图片
if (txtLogo.Text.Trim() != string.Empty)//如果有logo的话则添加logo
{
Bitmap btm = new Bitmap(txtLogo.Text);
Bitmap copyImage = new Bitmap(btm, image.Width / 5, image.Height / 5);
Graphics g = Graphics.FromImage(image);
int x = image.Width / 2 - copyImage.Width / 2;
int y = image.Height / 2 - copyImage.Height / 2;
g.DrawImage(copyImage, x, y);
}
picEncode.Image = image;
}
//保存二维码到磁盘
private void button3_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|PNG Image|*.png";
sfd.Title = "保存二维码";
sfd.FileName = string.Empty;
if (picEncode.Image != null)
{
if (sfd.ShowDialog() == DialogResult.OK && sfd.FileName != "")
{
using (FileStream fs = (FileStream)sfd.OpenFile())
{
switch (sfd.FilterIndex)
{
case 1:
picEncode.Image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case 2:
picEncode.Image.Save(fs, System.Drawing.Imaging.ImageFormat.Bmp);
break;
case 3:
picEncode.Image.Save(fs, System.Drawing.Imaging.ImageFormat.Gif);
break;
case 4:
picEncode.Image.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
break;
}
}
MessageBox.Show("保存成功!");
}
}
else
{
MessageBox.Show("抱歉,没有要保存的图片!");
}
}
//上传二维码照片
private void button2_Click(object sender, EventArgs e)
{
button8.Visible = true;
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|PNG Image|*.png";
if (ofd.ShowDialog() == DialogResult.OK)
{
String fileName = ofd.FileName;
picEncode.Image = new Bitmap(fileName);
}
}
//解码
private void button4_Click(object sender, EventArgs e)
{
if(picEncode.Image == null)
{
MessageBox.Show("请先上传二维码图片!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
try
{
string decodedString = new QRCodeDecoder().decode(new QRCodeBitmapImage(new Bitmap(picEncode.Image)), Encoding.UTF8);
txtData.Text = decodedString;
}
catch (Exception)
{
MessageBox.Show("抱歉,无法解码!");
}
}
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
//上传LOGO
private void button5_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|PNG Image|*.png";
if (ofd.ShowDialog() == DialogResult.OK)
{
txtLogo.Text = ofd.FileName;
}
}
//撤销LOGO
private void button9_Click(object sender, EventArgs e)
{
picEncode.Image = null;
txtLogo.Text = "";
}
private void textData_MouseClick(object sender, MouseEventArgs e)
{
txtData.Text = "";
}
private void label8_Click(object sender, EventArgs e)
{
Font f = new Font("Consolas", 14f, FontStyle.Regular);
label9.Font = f;
label10.Font = f;
Font font = new Font("Consolas", 14f, FontStyle.Underline | FontStyle.Italic);
label8.Font = font;
label5.Visible = false;
label6.Visible = false;
btnQRCodeForegroundColor.Visible = false;
btnQRCodeBackgroundColor.Visible = false;
button5.Visible = false;
txtLogo.Visible = false;
button9.Visible = false;
button7.Visible = true;
button6.Visible = false;
label1.Visible = true;
cbEncoding.Visible = true;
label4.Visible = true;
cbScale.Visible = true;
label2.Visible = true;
cbCorrectionLevel.Visible = true;
label3.Visible = true;
label3.Visible = true;
cbVersion.Visible = true;
}
private void label10_Click(object sender, EventArgs e)
{
Font f = new Font("Consolas", 14f, FontStyle.Regular);
label8.Font = f;
label9.Font = f;
Font font = new Font("Consolas", 14f, FontStyle.Underline | FontStyle.Italic);
label10.Font = font;
label1.Visible = false;
cbEncoding.Visible = false;
label4.Visible = false;
cbScale.Visible = false;
label2.Visible = false;
cbCorrectionLevel.Visible = false;
label3.Visible = false;
label3.Visible = false;
cbVersion.Visible = false;
label5.Visible = false;
label6.Visible = false;
btnQRCodeForegroundColor.Visible = false;
btnQRCodeBackgroundColor.Visible = false;
button7.Visible = false;
button6.Visible = false;
button5.Visible = true;
txtLogo.Visible = true;
button9.Visible = true;
}
private void label9_Click(object sender, EventArgs e)
{
Font f = new Font("Consolas", 14f, FontStyle.Regular);
label8.Font = f;
label10.Font = f;
Font font = new Font("Consolas", 14f, FontStyle.Underline | FontStyle.Italic);
label9.Font = font;
label1.Visible = false;
cbEncoding.Visible = false;
label4.Visible = false;
cbScale.Visible = false;
label2.Visible = false;
cbCorrectionLevel.Visible = false;
label3.Visible = false;
label3.Visible = false;
cbVersion.Visible = false;
button5.Visible = false;
txtLogo.Visible = false;
button9.Visible = false;
button7.Visible = false;
button6.Visible = true;
label5.Visible = true;
label6.Visible = true;
btnQRCodeForegroundColor.Visible = true;
btnQRCodeBackgroundColor.Visible = true;
}
private void button6_Click(object sender, EventArgs e)
{
btnQRCodeForegroundColor.BackColor = System.Drawing.Color.Black;
btnQRCodeBackgroundColor.BackColor = System.Drawing.Color.White;
}
private void button7_Click(object sender, EventArgs e)
{
cbVersion.Text = "7";
cbEncoding.Text = "Byte";
cbCorrectionLevel.Text = "M";
cbScale.Text = "5";
}
private void button8_Click(object sender, EventArgs e)
{
cbVersion.Text = "7";
cbEncoding.Text = "Byte";
cbCorrectionLevel.Text = "M";
cbScale.Text = "5";
btnQRCodeForegroundColor.BackColor = System.Drawing.Color.Black;
btnQRCodeBackgroundColor.BackColor = System.Drawing.Color.White;
txtData.Text = "";
picEncode.Image = null;
txtLogo.Text = "";
}
private void cbVersion_Click(object sender, EventArgs e)
{
MessageBox.Show("请尽量选择5-23范围内的Version值,确保生成的二维码能被准确解读","提示", MessageBoxButtons.OK,MessageBoxIcon.Information);
}
private void btnQRCodeBackgroundColor_Click(object sender, EventArgs e)
{
colorDialog2.ShowDialog();
btnQRCodeBackgroundColor.BackColor = colorDialog2.Color;
}
private void btnQRCodeForegroundColor_Click(object sender, EventArgs e)
{
colorDialog1.ShowDialog();
btnQRCodeForegroundColor.BackColor = colorDialog1.Color;
}
//隐藏textBox控件的竖形指针
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
private void btnQRCodeBackgroundColor_MouseDown(object sender, MouseEventArgs e)
{
HideCaret(btnQRCodeBackgroundColor.Handle);
}
private void btnQRCodeForegroundColor_MouseDown(object sender, MouseEventArgs e)
{
HideCaret(btnQRCodeForegroundColor.Handle);
}
private void btnQRCodeBackgroundColor_MouseUp(object sender, MouseEventArgs e)
{
HideCaret(btnQRCodeBackgroundColor.Handle);
}
private void btnQRCodeForegroundColor_MouseUp(object sender, MouseEventArgs e)
{
HideCaret(btnQRCodeForegroundColor.Handle);
}
}
}