Posts filed under 'Code Examples'

How To Create a CAPTCHA Graphic in VB.NET

An Example of a CAPTCHA Generated By This Class

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
            Exit Sub
        End If
        _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)
            End Using
            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)
            Next
            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))
            Next
            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))
            Next
        End Using
    End Sub

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.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

17 comments November 6th, 2007

Application Plug-ins Code Example Update

Update On Creating Application Plugins in VB.NET

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.

The Demo

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.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

6 comments November 5th, 2007

How To Create a Blog Badge in VB.NET

Visual Basic Notebook For .NET Blog Badge

I’m sure you’ve seen blog badges around like this around the Internet. Perhaps you’ve also wondered how to create one in VB.NET. Here’s a simple class that you can use to create 80×15 pixel badges. You could even add this class to your own ASP.NET web site and, with a little fleshing out, make your own badge generator.

The Basics

What we will be doing is creating a new 80×15 System.Drawing.Bitmap object. We will then create a Graphics object for the bitmap and drawing our rectangles and text on it. Then we’ll save the bitmap image out in PNG (Portable Network Graphics) format.

The Code

Here’s our code.

Public Class BlogButton

    Public Shared Sub GenerateBlogButton(ByVal buttonSaveLocation As String, ByVal leftText As String, ByVal leftTextColor As Color, _
                                         ByVal leftBackgroundColor As Color, ByVal rightText As String, ByVal rightTextColor As Color, _
                                         ByVal rightBackgroundColor As Color, ByVal borderColor As Color, ByVal backgroundColor As Color)
        Dim ButtonPicture As New Bitmap(80, 15)
        Using ButtonGraphics As Graphics = Graphics.FromImage(ButtonPicture)
            Dim ButtonFont As New Font("Verdana", 6, FontStyle.Regular)
            Dim TextBrush As New SolidBrush(leftTextColor)
            ButtonGraphics.Clear(backgroundColor)
            ButtonGraphics.DrawRectangle(New Pen(borderColor, 1), New Rectangle(0, 0, 79, 14))
            ButtonGraphics.FillRectangle(New SolidBrush(leftBackgroundColor), New RectangleF(2, 2, 31, 11))
            ButtonGraphics.FillRectangle(New SolidBrush(rightBackgroundColor), New RectangleF(34, 2, 44, 11))
            ButtonGraphics.DrawString(Mid(leftText.ToUpper, 1, 4), ButtonFont, TextBrush, 3, 3)
            ButtonGraphics.DrawString(Mid(rightText.ToUpper, 1, 8), ButtonFont, TextBrush, 34, 3)
            ButtonGraphics.Flush()
        End Using
        ButtonPicture.Save(buttonSaveLocation, System.Drawing.Imaging.ImageFormat.Png)
    End Sub

End Class

A few of things to note about the code.

First of all, why am I using the Mid function? Isn’t it suppose to be ‘evil’? I’m using it here because it can be used to limit the length of text in a very simple and readable manner. SubString(0,4) would throw an exception if the length was shorter than that. To avoid the exception and be “.NET Pure” I would have to have more length checking code in the routine. I decided not to do that and instead make use of a handy VB function that does this for me.

Another thing to note is that I’m using hardcoded values in several places. Since I’m working with a fixed size I didn’t go to the trouble of using constants or variables for these values. However, if I were to expand this implementation I would want to replace any hardcodes.

I’m not using any overloads on this function although it probably could benefit from some if it was production code. For example, you might want to have overloads for the size of the graphic and the font object or you might want to have an overload with fewer parameters for a default version.

Lastly, I made it shared so that it could be called without having to worry about the state of an object. You could create a version that did not use shared if you wanted.

More You Can Do

In addition to making the size flexible you could also add dynamic sizing between the right and left columns by using MeasureString. Using it to calculate the size of the passed in strings you could determine where to draw the rectangles. Another thing you could do is make the font changeable. 

You could also take this code and develop your own CAPTCHA or hit counter components. The basics would be the same. You could also take this same code and put it into a desktop app for graphic generation there although you might want to create a version that passes back a bitmap rather than writing it to disk.

Let me know if you have any questions or observations about this code sample by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

1 comment October 16th, 2007

How To Write an IsValidPath Function

Even works with messy disk drivesA common requirement that you may encounter is to have a way to validate a string to determine if it’s in the proper format for a path. While there are .NET functions that you can use that will tell you if a given path exists on the disk there is no built-in .NET function that will tell you if a path string has a valid format. This was the subject of a recent discussion on VBForums. In this article, we’ll look at the function I built and some other related ideas that were suggested.

Our Requirements

For this example, we want to create a function that will tell us if the path entered by a user is a valid path string or not. We aren’t concerned about it already existing on the disk or if we have the rights to create the folder. We only want to make sure that the path string has a valid format.

What Won’t Work

We can’t use methods that check the disk for existence of the folder because we don’t need it to actually exist yet. This means we can’t use the Directory.Exists functions from the IO Namespace or the My.Computer.FileSystem Namespace. Some other IO.Path functions, such as IsPathRooted (which was my first suggestion) and GetDirectoryName weren’t well suited for validating path names.

We could use a folder browser or the textbox file system autocomplete feature. However, this wouldn’t fulfill our validation requirement.

Two other methods were thought of by forumites were to create the directory temporarily and capture exceptions. The folder would be deleted if it wasn’t used. The problem here are the performance killing exceptions and the risk of leaving junk on a user’s drive. The second was to use System.IO.Path.GetFullPath. This method worked OK in some cases but had its own formatting quirks plus it required exception trapping to deal with incorrectly formatted paths.

Solving the Problem With Regular Expressions

The way I ended up suggesting to deal with the problem was to use regular expressions. Here is the function:

    Private Function IsValidPath(ByVal pathString As String) As Boolean
        Const PathPattern As String = "^(([a-zA-Z]:|\\)\\)?(((\.)|(\.\.)|([^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?))\\)*[^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?$"
        Dim Results As Boolean
        Try
            If System.Text.RegularExpressions.Regex.IsMatch(pathString , PathPattern) Then
                If IO.Path.GetPathRoot(pathString).Length >= 248 Then
                    Results = False
                Else
                    'additional checks could go here if desired
                    Results = True
                End If
            Else
                Results = False
            End If
        Catch ex As Exception
            Results = False
        End Try
        Return Results
    End Function

In this function you’ll notice that I first define a string constant with the regular expression string. I’ve ran several tests with it and it seems to work right but if you throw something at it that it can’t handle correctly, please let me know. Next, we look for a match between the pattern and the passed in string.

After passing the first test there is a second one. We need to determine if the path is too long. Windows paths can’t be longer that 247 characters. If this value is exceeded, a False value is return. Notice that there is room to add additional checks if you need them. For example, you could add a check for a local hard drive vs. a network or removable drive.

To call this function, you would just need to call it from the TextChanged event of the target textbox.

That’s my solution. I want to thank VBForum members stimbo, techgnome TokersBall_CDXX, penguin5000, VBDT, and JuggaloBrotha who participated in this discussion and rjbudz who got the whole thing started. If you have an idea or question on this function, please leave a comment here or in the VBForum thread linked at the top of the article.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

3 comments October 12th, 2007

How To Create Application Plug-ins In VB.NET

Plugging into an appSooner or later you’ll find that you want to make your application extensible. Perhaps you want to add customer specific processing modules to your backend processes. Maybe you’ll want to offer customers the ability to add their own functionality to your base application. VB.NET and the .NET Framework make this relatively easy to do. Let’s walk through the steps.

Define an Interface

The way to load a .NET assembly dynamically is through reflection. To make this process easier and more controllable within the context of an application I’ve found it best to define a plug-in interface, such as this one:

Public Interface IMyPlugIn

    Function TestFunction(ByVal value As String) As String

    Property MySetting() As String

End Interface

By using the interface this allows us to have a fixed definition for our plug-ins that our main application to work with. This means that we will need less main app code to support our plug-in.

Create A Class

Now we’re ready to create a plug-in class. Here’s the template that gets created:

Public Class CustomerXYZPlugin
    Implements MyPlugIn.IMyPlugIn

    Public Property MySetting() As String Implements MyPlugIn.IMyPlugIn.MySetting
        Get

        End Get
        Set(ByVal value As String)

        End Set
    End Property

    Public Function TestFunction(ByVal value As String) As String Implements MyPlugIn.IMyPlugIn.TestFunction

    End Function

End Class

Now, to complete the plug-in class we will need to add appropriate code it. You can’t define constructors in an interface so you’ll find it best to specify that you’ll either use a parameterless constructor or require that plug-in classes support a specific set of parameters. My preference has been to use parameterless ones and to supply ample properties for the plug-ins.

As for other code, as long as you define the interface you can do just about anything else you want.

Loading The Plug-In

Now we get to the heart of the matter, how to load the plug-in. There are several approaches you can take to this but here’s mine. First, let’s look at the code:

Private Function LoadPlugIn(ByVal LoadPath As String) As MyPlugIn.IMyPlugIn
    Dim NewPlugIn As MyPlugIn.IMyPlugIn
    Try
        Dim PlugInAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom(LoadPath)
        Dim Types() As Type
        Dim FoundInterface As Type
        Types = PlugInAssembly.GetTypes
        For Each PlugInType As Type In Types
            FoundInterface = PlugInType.GetInterface("MyPlugIn.IMyPlugIn")
            If FoundInterface IsNot Nothing Then
                NewPlugIn = DirectCast(PlugInAssembly.CreateInstance(PlugInType.FullName), MyPlugIn.IMyPlugIn)
                Exit For
            End If
        Next
    Catch ex As Exception
        'handle exceptions here
    End Try
    Return NewPlugIn
End Function

As you can see, we’re passing in the path to our plug-in and returning a plug-in interface object from the call. After declaring our return value we enter a try block. I recommend putting this loader logic in an exception handling block since you may be dealing with code that’s outside your direct control.

Next, we create a new Reflection.Assembly object from the file location that was passed into our function and extract the types from it. This allows a plug-in to have functionality beyond just the interface. We search for our interface and, when we find it, create a new instance and exit our search loop. Then we pass back the newly created plug-in object back to our main code.

Here’s a simple example of what the main code might look like:

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim NewPlugIn As MyPlugIn.IMyPlugIn = LoadPlugIn(TextBox1.Text)
    NewPlugIn.MySetting = "Hello World"
    Dim OurTestPlugInValue As String = NewPlugIn.TestFunction("Try It!")
End Sub

Those are the steps to adding a simple plug-in to your application. Of course, there are more things you can do with Reflection and I suggest that you investigate them if you’re thinking about implementing this in one of your apps. Remember that there is a performance penalty for using Reflection and there are security considerations as well so make sure you factor them into your design.

If you have any questions or observations about using Reflection to create plug-ins, let me know by leaving a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

9 comments October 9th, 2007

Previous Posts


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives