In this article we’ll be creating a class to generate CAPTCHA graphics that you can use on web sites to help authenticate users as being human and not an automated process.
What Is CAPTCHA
CAPTCHA is an abbreviation for Completely Automated Public Turing test to tell Computers and Humans Apart. This method uses images of words or numbers that are, in theory, distorted and jumbled enough so that an optical character recognition program can’t read them but a human should be able to do so easily.
I’m not a big fan of this method myself since I think it interferes with the user experience. However, there is plenty of demand for them to be placed into systems that interact with the public on the Internet.
The CAPTCHA Class
You can download the CAPTCHA class source code here.
This class is a simple one that builds a 5 character numeric string and places it on a grid background with random ‘noise’. Our properties include the height, width, and font along with the randomly generated value between 10000 and 99999 and the matching bitmap. The new method is available as a parameterless version for subclassing and one that allows you to pass in the height, width, and font.
The core routine is the GenerateNewCaptcha shown here:
Public Sub GenerateNewCaptcha()
If _captchaFont Is Nothing OrElse _captchaHeight = 0 OrElse _captchaWidth = 0 Then
_captchaCode = RandomValue.Next(10000, 100000).ToString
_captchaImage = New Bitmap(_captchaWidth, _captchaHeight)
Using CaptchaGraphics As Graphics = Graphics.FromImage(CaptchaImage)
Using BackgroundBrush As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.SmallGrid, Color.DimGray, Color.WhiteSmoke)
CaptchaGraphics.FillRectangle(BackgroundBrush, 0, 0, _captchaWidth, _captchaHeight)
Dim CharacterSpacing As Integer = (_captchaWidth \ 5) - 1
Dim HorizontalPosition As Integer
Dim MaxVerticalPosition As Integer
For Each CharValue As Char In _captchaCode.ToCharArray
MaxVerticalPosition = _captchaHeight - Convert.ToInt32(CaptchaGraphics.MeasureString(CharValue, _captchaFont).Height)
CaptchaGraphics.DrawString(CharValue, _captchaFont, Brushes.DimGray, HorizontalPosition, RandomValue.Next(0, MaxVerticalPosition))
HorizontalPosition += CharacterSpacing + RandomValue.Next(-1, 1)
For Counter As Integer = 0 To 24
CaptchaGraphics.FillEllipse(Brushes.DimGray, RandomValue.Next(1, _captchaWidth), RandomValue.Next(1, _captchaHeight), RandomValue.Next(1, 4), RandomValue.Next(1, 4))
For Counter As Integer = 0 To 24
CaptchaGraphics.FillEllipse(Brushes.WhiteSmoke, RandomValue.Next(1, _captchaWidth), RandomValue.Next(1, _captchaHeight), RandomValue.Next(1, 4), RandomValue.Next(1, 4))
Let’s look at some of the details of this routine.
First, notice that we’re generating random numbers in several places, most notably to generate the main code value. We also use random numbers to place the numbers and the noise bits.
The HatchBrush object is used to draw the grid background. This style could be changed to a different pattern. There are several variations you could try to get a unique effect. You could even randomize the background.
The characters from the randomly generated number are drawn onto the graphic one character at a time and are randomly placed along the vertical axis and slightly off kilter on the horizontal one.
The FillEllipse method of the Graphics object is used to create the noise at 50 different random points on the graphic. These little marks help obscure the actual characters from OCR’s and sometimes from humans as well.
Using the Class
Using the class is simple. You just create the class, display the graphic from it and verify user input against the value stored in the class. You can also regenerate the value if the user requests it. Remember that you will need to save the generated bitmap to disk in order to display it to a web user in an ASP.NET application.
More You Can Add
There are several things you could add to this class to enhance it. You could:
- Add the ability to accept strings
- Add the ability to dynamically size the strings and the resulting bitmap
- Add more distortion by using Graphics method to twist the output
- Add more background noise options
That’s all for this example. Let me know if you have any questions or observations by this example by leaving me a comment.
November 6th, 2007
As a follow-up to my previous article, How To Create Application Plug-ins In VB.NET, Karl Stoney asked for a more complete example. Hopefully this update will help.
Tips and Tricks
One trick you can use to make your development of these plugins easier is to have multiple projects in your solution. In the case of the demo app I added the main demo project, the interface project, and the two plugin projects to the solution. If I wanted to have another plugin, I would just add it to this solution. This makes debugging easier and saves system memory somewhat vs. running separate instances of Visual Studio
Another trick is to change the compile output folder to a common folder. This puts all of the executable in the same folder, once again for easy debugging. Remember that your plugins when deployed must be in the same folder as the calling application.
In this code example, we have a PluginDemo application that can call various plugins that conform to the IMyPlugIn interface. We also have a PlugIn1 and a PlugIn2 projects that implement the interface in different ways. PlugIn1 uses a standard message box while PlugIn2 uses a custom form.
The core code itself isn’t any different from the code presented in the previous article. The LoadPlugIn routine is the key to using Reflection to load the plugin. To get a better understanding of how it all comes together I recommend stepping through the process as it runs.
The zip file contains the project code but I excluded the executables. After unzipping the project you will need to first build the PlugInInterface project by itself. This will create the DLL that the other 3 projects need to reference. Once you’ve done this, do a Build Solution and it should be ready to run.
Here’s the demo zip file: VB.NET Application Plugin Demo
Let me know if you have any questions about this demo or application plug-ins in VB.NET.
November 5th, 2007
Back From a Hiatus
I took about a week hiatus from VB Notebook For .NET while I was working on my other, general topic, blog, OpTempo, and another yet-to-be-released web project but I’m back working on this site now. I just need to figure out a good way to do ‘re-runs’ the next time I take a break or work on other projects.
Coming Up This Week
I’ve got my follow-up article on coaching that I should publish this week as well as a few follow-up and new article and demos. If you have a topic you would like for me to cover, let me know in a comment or email.
November 5th, 2007
Here’s installment #6 of my VB.NET interview questions series.
Previous Installments: #1, #2, #3, #4 , #5
Feel free to add a comment with your answers. Try to answer them before looking at the comments or searching MSDN or Google for an extra challenge.
True Or False
1. Base-class constructors are not inherited by derived classes.
2. A class may only implement a single interface.
3. A checkbox may have either a square or circular appearance.
4. HttpSessionState can only store string values.
5. A page object’s IsPostBack property is used to determine if the page is being loaded due to a postback.
General VB.NET Questions
1. Should you throw exceptions in the Finally block? Why or why not?
2. How do you create a scrolling region on a form?
3. What are some differences between CType and DirectCast?
4. Should you use a "sp_" prefix on SQL Server stored procedures? Why or why not?
5. If you have an ASP.NET application with a Master Page how can you change meta data from child pages?
Tough General Interview Questions
1. How do you think your previous experience will help you perform your work here?
2. Would you say that you’re a competitive person? Why or why not?
3. Why did you decided to get a degree in [job candidates college major]?
4. Why do you want to work at [insert company name here]?
5. Give an example of how you applied creativity in your current/former job?
Open Ended Questions
1. Describe what you consider to be best practices for creating a testing environment.
2. You are given the task of developing an interface to a vendor’s web service. The documentation is very minimal for it and may be outdated. What approach would you take to developing this interface?
Have fun with these and let me know what you think about them by leaving a comment or answering the questions.
October 28th, 2007
One problem some programmers new to VB.NET and object oriented programming in general have is understanding interfaces and how they related to classes. In this article, we’ll take an introductory look at interfaces and some of the ways you can use them in your VB.NET applications.
What is an Interface?
To put it in simple terms, an interface is a definition of methods and properties. Sometimes this is referred to as a ‘contract’. If a class agrees to implement an interface it must implement all of the properties and methods defined.
One difference you’ll see in an interface vs. a class is that there is no code, only the templates, aka contracts, for the properties and methods. You’ll also notice that there is no access level defined. It’s always considered public.
Here’s an example interface:
Public Interface IPerson
Property ID() As Integer
Property FirstName() As String
Property LastName() As String
This means that if a class implements the IPerson interface it will have to implement these routines. Here’s an example of a class implementing this interface:
Public Class Customer Implements IPerson
Protected _id As Integer
Protected _firstName As String Protected _middleName As String
Protected _lastName As String
Public Property ID() As Integer Implements IPerson.ID
Set(ByVal value As Integer)
_id = value
Public Property FirstName() As String Implements IPerson.FirstName
Set(ByVal value As String)
_firstName = value
Public Property MiddleName() As String
Set(ByVal value As String)
_middleName = value
Public Property LastName() As String Implements IPerson.LastName
Set(ByVal value As String)
_lastName = value
End PropertyEnd Class
As you can see, each of the properties above, except for MiddleName, has an Implements statement that defines how it will fulfill the Interface contract. The rule is that you can add to the interface inside the implementing class but you can’t take away.
Remember that implementing an interface isn’t the same as creating an instance of a class or creating a subclass. All you’re doing is defining how the external interface should look, not what goes on inside. People do get confused over that point.
Interfaces can be very simple or complex. Most current OOP thought suggests that interfaces be limited to a single method. For example, you might have an IUpdate interface that defines a single Update function and you might have another interface called ICreate that defines a single Create function. You would then combine them into classes that needed to implement them, as in this example:
Public Interface ICreate
Function CreateNew(ByVal id As Integer) As Boolean
Public Interface IUpdate
Function Update(ByVal id As Integer) As Boolean
Public Class Customer
Implements IPerson, IUpdate, ICreate
As you can see, a class can implement multiple interfaces. Whether it’s better to design with a lot of different interfaces or to group them into logical sections is really up to your own needs. My own take is a bit of a compromise in that I keep them simple with just a few tightly related methods or properties but I don’t religiously limit each interface to a single item.
Another use for interfaces is in defining a common interface for a plug-in architecture as I mentioned in this previous article: How To Create Application Plug-ins In VB.NET. In this case, you will want to have a more complex interface design in most cases since your main app will need a stronger connection to the plug-in.
Do you have any questions about using Interfaces in VB.NET? Please feel free to leave a comment and ask about it.
October 23rd, 2007