在大部分WEB程序中,验证码控件的使用时非常常见而且非常必要的,原因大家都应该知道,我就不罗嗦了。但是在WinForm程序中,是否有必要加上一个验证码控件?个人认为,一般的个人使用或者小范围使用的程序中,这个是没有必要的;但是相对公共的桌面应用程序中,加上一个验证码控件也许会更加安全。
现在我给大家介绍一下我自己写的一个比较简单的验证码控件。
基本原理:生成一些随机数,然后将这些随机数画在一个Bitmap对象中,并对这个Bitmap进行加噪点,扭曲,画干扰线等等,最后放入一个PictureBox容器中显示出来。
步骤:
① 首先创建一个“Windows 控件库项目”并命名为“VerificationCode”。
② 打开解决方案,重命名“UserControl1.cs”为“VerificationCode.cs”。
③ 双击打开“VerificationCode.cs”,在其容器内添加一个PictureBox控件,并重命名为PicCodeImage
④ 转到代码界面,开始编辑代码。
首先,创建控件的属性和字段,其中Code供外部获取随机生成的验证码,CodeLenght供外部设置生成验证码的长度,默认为4。代码如下:
//弦值
private static double PI2 = 6.283185307179586476925286766559;
private string _Code;
/// <summary>
/// 验证码
/// </summary>
public string Code
{
get
{
return _Code;
}
}
private int _CodeLength = 4;
/// <summary>
/// 验证码长度
/// </summary>
public int CodeLength
{
set
{
_CodeLength = value;
}
}
然后,创建生成随机验证码的函数,并根据随机验证码生成图片并加噪扭曲的函数。代码如下:
/// <summary>
/// 生成图片
/// </summary>
/// <param name="code">验证码表达式</param>
private Bitmap CreatImage(string code)
{
Bitmap image = new Bitmap((int)Math.Ceiling(code.Length * 19.5), 40);
//创建画布
Graphics g = Graphics.FromImage(image);
Random random = new Random();
//图片背景色
g.Clear(Color.White);
//画图片背景线
for (int i = 0; i < 10; i++)
{
int x1 = random.Next(image.Width);
int x2 = random.Next(image.Width);
int y1 = random.Next(image.Height);
int y2 = random.Next(image.Height);
g.DrawLine(new Pen(Color.Black), x1, y1, x2, y2);
}
//画图片的前景噪音点
for (int i = 0; i < 50; i++)
{
int x = random.Next(image.Width);
int y = random.Next(image.Height);
image.SetPixel(x, y, Color.FromArgb(random.Next()));
}
Font font = new Font("Couriew New", 22, FontStyle.Bold);
System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush
(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.SkyBlue, 1.2f, true);
int w = 2;
int h = 1;
g.DrawString(code, font, brush, w, h);
image = TwistImage(image, true, 5, 5);
//画图片的边框线
g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
return image;
}
///<summary>
///正弦曲线Wave扭曲图片
///</summary>
///<param name="srcBmp">图片路径</param>
///<param name="bXDir">如果扭曲则选择为True</param>
///<param name="nMultValue">波形的幅度倍数,越大扭曲的程度越高,一般为3</param>
///<param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>
///<returns></returns>
private Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
{
Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
// 将位图背景填充为白色
Graphics graph = Graphics.FromImage(destBmp);
graph.FillRectangle(new SolidBrush(Color.White), 0, 0, destBmp.Width, destBmp.Height);
graph.Dispose();
double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;
for (int i = 0; i < destBmp.Width; i++)
{
for (int j = 0; j < destBmp.Height; j++)
{
double dx = 0;
dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
dx += dPhase;
double dy = Math.Sin(dx);
// 取得当前点的颜色
int nOldX = 0, nOldY = 0;
nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
nOldY = bXDir ? j : j + (int)(dy * dMultValue);
System.Drawing.Color color = srcBmp.GetPixel(i, j);
if (nOldX >= 0 && nOldX < destBmp.Width
&& nOldY >= 0 && nOldY < destBmp.Height)
{
destBmp.SetPixel(nOldX, nOldY, color);
}
}
}
return destBmp;
}
最后,添加picCodeImage的Click事件,并在事件中触发生成验证码的函数,并将生成的Bitmap作为picCodeImage的图像源;同时在控件初始化时也触发该函数。代码如下:
public VerificationCode()
{
InitializeComponent();
picCodeImage.Image = CreatImage(CreatRandomCode(_CodeLength));
}
private void picCodeImage_Click(object sender, EventArgs e)
{
picCodeImage.Image = CreatImage(CreatRandomCode(_CodeLength));
}
大功告成了!现在可以在一个测试项目中,先给工具栏添加该自定义控件,然后拖放到一个Form中,调用方法为:
if (verificationCode1.Code == textBox1.Text.Trim())
{
MessageBox.Show("验证码正确");
}
else
{
MessageBox.Show("验证码错误");
}
注意:在使用该控件时,可先行设置一下CodeLength属性,默认为4,该属性可控制生成验证码的长度。