65.9K
CodeProject 正在变化。 阅读更多。
Home

防机器人提交表单

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.36/5 (5投票s)

2008年4月4日

CPOL

5分钟阅读

viewsIcon

25893

downloadIcon

133

以下脚本使自动工具难以提交表单。此基本脚本涉及的步骤包括:创建绘图空间、分配颜色、填充背景、绘制字符、添加失真以及将图像输出到浏览器。

Article.GIF

引言

以下脚本使自动工具难以提交表单。此基本脚本涉及的步骤包括:创建绘图空间、分配颜色、填充背景、绘制字符、添加失真以及将图像输出到浏览器。

使用 GDI+ 进行绘图

GDI+ 是 .NET 应用程序的全能绘图模型。GDI+ 在 .NET 中有多种用途,包括将文档写入打印机、在 Windows 应用程序中显示图形以及在网页中渲染图形。使用 GDI+ 代码绘制图形比使用静态图像文件速度慢。但是,它为您提供了更大的自由度,并实现了早期 Web 开发平台(如经典 ASP)中不可能实现(或非常困难)的几个可能性。例如,您可以创建包含用户特定信息的丰富图形,并且可以根据数据库中的记录即时渲染图表和图形。GDI+ 编程的核心是 System.Drawing.Graphics 类。Graphics 类封装了一个 GDI+ 绘图表面,无论是窗口、打印文档还是内存中的位图。ASP.NET 开发人员很少需要绘制窗口或打印文档,因此最后一个选项是最实用的。要在 ASP.NET 中使用 GDI+,您需要遵循四个步骤:

  1. 创建您将在其中执行所有绘图操作的内存位图。
  2. 为图像创建 GDI+ 图形上下文。这将为您提供所需的 System.Drawing.Graphics 对象。
  3. 使用 Graphics 对象的方法执行绘图。您可以绘制和填充线条和形状,甚至可以从现有文件中复制位图内容。
  4. 使用 Response.OutputStream 属性将图像的二进制数据写入浏览器。

在接下来的几节中,您将看到几个使用 GDI+ 的网页示例。在继续之前,您可能需要确保已导入以下命名空间:

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging; 

System.Drawing 命名空间定义了许多绘图的基本要素,包括画笔、笔刷和位图。默认情况下,Visual Studio 会将 using 语句添加到您所有网页中,以导入这些命名空间。System.Drawing.Drawing2D 命名空间添加了其他有用的细节,例如灵活的 GraphicsPath 类,而 System.Drawing.Imaging 包含 ImageFormat 命名空间,该命名空间允许您选择在将位图渲染到客户端时使用的图形格式。

简单绘图

以下示例演示了最简单的 GDI+ 页面。所有工作都在 Page.Load 事件处理程序中执行。第一步是通过创建 System.Drawing.Bitmap 类的实例来创建内存位图。创建此对象时,您需要在构造函数参数中指定图像的宽度和高度(以像素为单位)。您应该尽可能减小尺寸。较大的位图不仅会在代码执行期间消耗额外的服务器内存,还会增加发送到客户端的渲染内容的尺寸,从而减慢传输速度。

// Create the in-memory bitmap where you will draw the image. 
// This bitmap is 300 pixels wide and 50 pixels high. 
Bitmap image = new Bitmap(300, 50);

下一步是为图像创建 GDI+ 图形上下文,该上下文由 System.Drawing.Graphics 对象表示。此对象提供了允许您在内存位图上绘制内容的方法。要从现有 Bitmap 对象创建 Graphics 对象,只需使用 static Graphics.FromImage() 方法,如下所示:

Graphics g = Graphics.FromImage(image);  

现在是时候进行有趣的部分了。使用 Graphics 类的各种方法,您可以绘制文本、形状和图像到位图上。在此示例中,绘图代码非常简单。它使用 Graphics 对象的 FillRectangle() 方法以纯白色背景填充图形。

// Draw a solid white rectangle. 
// Start from point (1, 1). 
// Make it 298 pixels wide and 48 pixels high. 
g.FillRectangle(Brushes.White, 1, 1, 298, 48);

FillRectangle() 方法需要几个参数。第一个参数设置颜色,接下来的两个参数设置起始点,最后两个参数设置宽度和高度。在测量像素时,点 (0, 0) 是图像的左上角,以 (X, Y) 坐标表示。X 坐标向右增加,Y 坐标向下增加。在当前示例中,图像宽度为 300 像素,高度为 50 像素,这意味着点 (300, 50) 是右下角。在此示例中,FillRectangle() 方法并没有完全填充整个位图。相反,它在四周留出了 1 像素宽的边框。由于您没有在此区域绘制任何内容,因此这些像素将具有默认颜色(对于渲染为 GIF 格式的位图,该颜色为黑色)。下一部分绘图代码会渲染一个静态标签消息。要做到这一点,您需要创建一个 System.Drawing.Font 对象来表示您要使用的字体。这不应与您与 ASP.NET 控件一起使用的 FontInfo 对象混淆,后者用于指定网页的请求字体。与 FontInfo 不同,Font 表示一个单一的、特定的字体(包括字体类型、大小和样式),该字体安装在当前计算机上。创建 Font 对象时,您需要指定字体名称、磅值和样式,如下所示:

Font font = new Font("Impact", 20, FontStyle.Regular);

***由于此图像是在服务器上生成的,因此您可以在创建图形时使用服务器安装的任何字体。客户端不需要安装相同的字体,因为客户端接收的是已渲染的图像文本。要渲染文本,您需要使用 Graphics 对象的 DrawString() 方法。与 FillRectangle() 对象一样,您需要指定绘图开始的坐标。此点表示文本块的左上角。在本例中,使用了点 (10, 5),这意味着距离左侧 10 像素,距离顶部 5 像素。

g.DrawString("This is a test.", font, Brushes.Blue, 10, 5);

图像完成后,您可以使用 Image.Save() 方法将其发送到浏览器。从概念上讲,您将图像“保存”到浏览器的响应流中。然后,它会被发送到客户端并在浏览器中显示。使用此技术时,您的图像将替换任何其他网页数据,并绕过 Web 控件模型。

// Render the image to the output stream.
 image.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);

您可以将图像保存到任何有效的流中,包括 FileStream。此技术允许您将动态生成的图像保存到磁盘,以便以后在其他网页中使用。最后,您应该在完成后显式释放图像和图形上下文,因为它们都占用了某些非托管资源,如果不显式释放,这些资源不会立即被释放。您可以通过调用 Dispose() 方法来释放资源,如下所示:

g.Dispose();
image.Dispose();

Article2.GIF

防机器人图像生成器代码

public partial class RndImg : System.Web.UI.UserControl 
{ 	
	private StringBuilder str = new StringBuilder();
	private bool ABrush = true;
	public bool DefaultRandomBrush
	{ 
		get { return ABrush; }
		set { ABrush = value; }
	} 
	private int backden = 500; 
	public int BackgroundDensity 
	{ 
		get { return backden; } 
		set { backden = value; } 
	} 
	public string Output() 
	{ 
		return Session["Out"].ToString(); 
	} 
	public void Fresh(object sender, EventArgs e) //For redraw bot-proof image
	{ 
		Page_Load(sender, e); 
	} 
	protected void Page_Load(object sender, EventArgs e) 
	{ 
		float temp = 0; 
		Random rnd = new Random(unchecked((int)DateTime.Now.Ticks)); 
		char ch = '1'; 
		Bitmap image = new Bitmap(180, 60); 
		Graphics g = Graphics.FromImage(image); 
		g.FillRectangle(Brushes.WhiteSmoke, 1, 1, 178, 58); 
		Font font = new Font("Monotype Corsiva", 30, FontStyle.Italic); 
		SizeF size = new SizeF(); 
		backbround(g, 180,60); 
		Brush[] myBrush ={Brushes.Red, 
				Brushes.Blue, 
				Brushes.DarkBlue, 
				Brushes.Violet, 
				Brushes.Tomato, 
				Brushes.Black, 
				Brushes.Chocolate, 
				Brushes.Brown}; 
		SolidBrush mysBrush; 
		for (int i = 0; i < 4; i++) 
		{ 
			ch = Convert.ToChar((int)((rnd.NextDouble() * 25) + 65)); 
			if (ABrush == false) 
			{ 
				mysBrush = new SolidBrush
				(Color.FromArgb((int)(rnd.NextDouble() * 255), 
				(int)(rnd.NextDouble() * 255), 
				(int)(rnd.NextDouble() * 255)));
				g.DrawString(ch.ToString(), font, 
				mysBrush, temp, (int)(rnd.NextDouble() * 20)); 
			} 
			else 
			{ 
				g.DrawString(ch.ToString(), font, 
				myBrush[(int)(rnd.NextDouble() * myBrush.Length)],
				temp, (int)(rnd.NextDouble() * 20)); 
			} 
			size = g.MeasureString(ch.ToString(), font); 
			temp += size.Width; 
			str.Append(ch); 
		} 
		image.Save(Server.MapPath("")+@"\a32166g9.gif", ImageFormat.Gif); 
		Page.Unload += new EventHandler(Page_Unload); 
	} 
	void Page_Unload(object sender, EventArgs e) 
	{ 
		Session["Out"] = str.ToString(); 
	} 
	private void backbround(Graphics gr, int width, int hieght)// 
	{ 
		Random rnd = new Random(unchecked((int)DateTime.Now.Ticks)); 
		int x2 = 0, y2 = 0; 
		int x = 0, y = 0; 
		for (int i = 0; i < backden; i++) 
		{ 
			x = (int)(rnd.NextDouble() * width); 
			y = (int)(rnd.NextDouble() * hieght); 
			x2 = (int)(rnd.NextDouble() * 5); 
			y2 = (int)(rnd.NextDouble() * 5); 
			Pen p = new Pen(Color.FromArgb((int)(rnd.NextDouble() * 255), 
				(int)(rnd.NextDouble() * 255), 
				(int)(rnd.NextDouble() * 255))); 
			gr.DrawLine(p, new Point(x, y), new Point(x + x2, y + y2)); 
		} 
	} 
}

历史

  • 2008 年 4 月 4 日:首次发布
© . All rights reserved.