當初學習一般處理程序的時候,寫過一個驗證碼,不過是后台程序向前台輸出了一張圖片,圖片上是幾個隨機寫上去的字符。雖然也驚訝於許多網站上那些“扭曲”的驗證碼,卻琢磨不透人家是怎么實現的,后來逐漸把這事遺忘了。今天在網上碰巧看到有人用php實現的案例,忍不住想着用C#來一把。當然,在此先感謝網上那位仁兄提供的思路,在下只是比着葫蘆畫瓢。
這里所說的“扭曲”的驗證碼,只是字符扭曲。由於時間倉促,我也沒給顧得上添加圖片噪點。先說思路:創建圖片A做為背景,其次創建圖片B,在圖片B畫上驗證碼文字,然后將圖片B拆分成若干部分畫到圖片A上。打個比方,好比是把一張畫縱向平均裁成若干份,然后再上下交錯着粘到另一張白紙上。如果隨意的上下交錯排列,看到的八成就是一片亂七八糟的玩意兒,這里不妨按照一個曲線變化的規律來排列,我選擇的是正弦曲線。
步驟:
1、新建一般處理程序TestCodeHandler.ashx,先定義一個隨機生成驗證碼文字的方法,如下:
/// <summary> /// 隨機生成驗證碼 /// </summary> /// <returns></returns> public string GetTestCode() { Random r = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { int n = r.Next(65, 91); sb.Append((char)n); } return sb.ToString(); }
2、在ProcessRequest方法中,確定輸出文件的類型。
context.Response.ContentType = "image/jpeg";
3、引用命名空間System.Drawing和using System.Drawing.Imaging,生成驗證碼圖片。
using (Image img = new Bitmap(85, 40))//背景圖片 { using (Image fontImg = new Bitmap(84, 38))//預先畫驗證碼的臨時圖片 { //先將驗證碼畫到臨時圖片fontImg上 using (Graphics fontGraphic = Graphics.FromImage(fontImg)) { fontGraphic.Clear(Color.White);//將畫布塗白 //畫驗證嗎 fontGraphic.DrawString(GetTestCode(), new Font("宋體", 18, FontStyle.Italic | FontStyle.Bold), Brushes.Black, new PointF(4, 4)); } //將臨時驗證碼圖片fontImg分成若干份畫到背景圖片img上 using (Graphics g = Graphics.FromImage(img)) { g.Clear(Color.White);//將畫布塗白 int sum = 60;//分成60份 int niu = 6;//上下最多偏移10像素 float x = 0, y = 1;//從臨時圖片fontImg選取矩形區域的起始坐標 //從臨時圖片fontImg選取矩形區域的寬度,由於有背景圖片映襯,這里只確定寬度 float width = ((float)fontImg.Width) / sum; //依次把臨時圖片fontImg各部分畫到背景圖片上 for (int i = 0; i < sum; i++) { //獲取當前部分的正弦值,計算上下偏移量。但這樣會使驗證碼的扭曲單一 float rate = (float)Math.Sin(360 * 1.0 / sum * i / 180 * Math.PI) * niu; //如果使用隨機數,會有不同的變化 //Random r = new Random(DateTime.Now.Millisecond); //float rate = (float)Math.Sin(360 * 1.0 / sum * i / 180 * Math.PI) * r.Next(1,niu); //把臨時圖片fontImg當前部分畫到背景圖片上 g.DrawImage(fontImg, new Rectangle(x==0?1:(int)x, (int)y, img.Width, img.Height - 2), x, y * rate, width, fontImg.Height, GraphicsUnit.Pixel); //依次改變橫坐標的下一個位置 x += width; } //為背景圖片畫邊框 g.DrawRectangle(new Pen(Brushes.Black), new Rectangle(0, 0, img.Width - 1, img.Height - 1)); } } //將背景圖片保存到輸出流 img.Save(context.Response.OutputStream, ImageFormat.Jpeg);
4、測試。新建html頁面,添加<img>標簽,令src屬性指向TestCodeHandler.ashx,並為它的onclick事件注冊方法,實現點擊切換圖片的效果。如下:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> function change() { document.getElementById("img").src = "TestCodeHandler.ashx?id=" + new Date().getTime(); } </script> </head> <body> <img id="img" src="TestCodeHandler.ashx" onclick="change()"/> </body> </html>
5、效果如下:
恕在下能力一般,水平有限,也只能實現上面的效果。若有高人看到此文,發現有不到之處,還望不吝賜教。
