Generate Dynamic Buttons

Create Attractive Image Buttons Instantly at Run Time

ControlFreak

LANGUAGES: VB.NET | C#

ASP.NET VERSIONS: 3.5

 

Generate Dynamic Buttons

Create Attractive Image Buttons Instantly at Run Time

 

By Steve C. Orr

 

Standard HTML buttons are sturdy and functional, yet their ugly gray interface renders them fairly useless for design-conscious Web sites. For this reason, most Web sites tend to use the ImageButton control much more often than the Button control. Of course, the main problem with ImageButtons is the need to create and maintain all those images. And if your customers are like most, they likely change their minds several times during the development process about exactly which colors they d like to see on their buttons. Such innocently na ve requests can generate lots of rework that tends to suck away time from other important development tasks. They don t understand how simply changing a color or two can take so much work and trying to explain it to them can end up sounding whiney and unprofessional.

 

By examining the dynamic button generation techniques detailed here, you can learn how to satisfy such customer requests easily and promptly. You ll see how with a little forethought button images can be changed, site-wide and instantaneously, with no more than a few keystrokes. As a result, you ll find yourself spending a lot less time mucking around in Photoshop so you can progress toward more important work.

 

Creating the Image

At the heart of every image button is an image. The DynaBtn class listed in Figure 1 can create just such an image dynamically at run time. Simply feed the GenButton function some basic parameters (for the text to be displayed, the colors to be used, and the desired margins) and it will return a bitmap that matches your specifications. This class could be compiled into its own DLL for optimal reuse, or it could simply be included in the App_Code folder of an ASP.NET Web application.

 

Imports System.Drawing

Imports System.Drawing.Imaging

Public Class DynaBtn

 Public Shared Function GenButton( _

   ByVal text As String, _

   ByVal backColor As Color, _

   ByVal foreColor As Color, _

   ByVal font As Font, _

   ByVal padH As Integer, _

   ByVal padV As Integer) As Bitmap

   'create a starter image

   Dim bmp As New Bitmap(1, 1, _

       PixelFormat.Format32bppRgb)

   Dim g As Graphics = Graphics.FromImage(bmp)

   'measure the size needed for the specified text & font

   Dim size As SizeF = g.MeasureString(text, font)

   'add some size for the margins

   Dim width As Integer = Convert.ToInt32( _

       size.Width + (PadH * 2))

   Dim height As Integer = Convert.ToInt32( _

       size.Height + (PadV * 2))

   'now recreate the image at the correct size

   bmp = New Bitmap(width, _

                    height, _

                    PixelFormat.Format32bppRgb)

   g = Graphics.FromImage(bmp)

   'fill it with the background color

   Dim brush As New SolidBrush(backColor)

   g.FillRectangle(brush, 0, 0, width - 1, height - 1)

   'now draw the text with the specified forecolor

   Dim brush2 As New SolidBrush(foreColor)

   g.DrawString(text, font, brush2, PadH, PadV)

   Return bmp

 End Function

End Class

Figure 1: The DynaBtn class can be used to dynamically generate ImageButton images as needed at run time.

 

The first code block in Figure 1 creates a throw-away bitmap used primarily for initial measurement purposes. The second code block does the actual measuring; it determines how large the button will need to be in order to display the specified text with the specified font. The third code block adds a bit of padding onto that measurement for margins.

 

Now that all the required sizes have been calculated, the fourth code block in Figure 1 begins the creation of the real bitmap that will be displayed to the user. A standard 32-bit RGB bitmap is specified here, although many other (less common) options are available if you re feeling adventurous.

 

Finally, brushes are created to fill the button with the specified background color and draw the specified text onto the button. The resulting bitmap is returned by the function.

 

Figure 2 displays an optional overloaded version of the GenButton function. This overloaded GenButton function simply calls the original GenButton function (listed in Figure 1) after setting some hard-coded default parameters. Hard-coding defaults in this way can be acceptable in some situations, although later in this article we ll explore preferable techniques for configuring them.

 

Public Shared Function GenButton( _

   Optional ByVal text As String = "Submit") As Bitmap

   'create defaults

   Dim PadH As Integer = 5

   Dim PadV As Integer = 5

   Dim font As Font = New Font("Arial", 10)

   Dim BackColor As Color = Color.LightSkyBlue

   Dim ForeColor As Color = Color.DarkBlue

   Return GenButton( _

       text, _

       BackColor, _

       ForeColor, _

       font, _

       PadH, _

       PadV)

End Function

Figure 2: This overloaded version of the GenButton function simplifies the parameter list at the expense of some flexibility.

 

This GenButton function can be called with a simple line of code, such as:

 

Dim bmp As Bitmap = DynaBtn.GenButton("Log In")

 

A Windows Forms application could then directly display this bitmap in a PictureBox control, although Web developers have an extra step or two that must be dealt with to get the image displayed in the correct place at the correct time (see Figure 3).

 


Figure 3: This is a basic button generated dynamically at run time by the GenButton function of the DynaBtn class.

 

Displaying the Image

For an image to be displayed on a Web page, it must be referenced by that Web page. Images are referenced from Web pages with a standard HTML tag, which is often generated by ASP.NET controls such as the Image and ImageButton controls.

 

A Web page that contains an image requires at least two separate browser requests: one for the textual page content and one for the image. This necessitates a separate handler to deal with the separate image request. Standard Web forms (ASPX pages) and HTTP handlers are both reasonable solutions for responding to such requests. An HTTP handler can be slightly more efficient, because it avoids most of the superfluous HTML handling routines. However, the ASPX-based solution is simpler to implement, and, if done right, it too can evade almost as much of the unnecessary HTML handling routines. The DynaBtn class listed earlier can be used by either of these image-serving techniques.

 

An ASPX Image Server

To create an ASPX page to serve up the dynamic button images, first add a new Web form to an ASP.NET Web application. Choose a short unique filename such as DynBtn.aspx. You can remove all the HTML from this Web form because this special page will be emitting an image instead of HTML. All the real work will happen in the code-behind for this page.

 

It s best to render the image as early as possible in the page lifecycle to efficiently evade most of the Web page s superfluous HTML handling routines. In this case, the PreInit event is adequate for this goal (Figure 4 shows how it s done).

 

'Imports System.Drawing

Protected Sub Page_PreInit(ByVal sender As Object, _

                       ByVal e As System.EventArgs) _

                       Handles Me.PreInit

 Response.Clear() 'Delete any HTML buffered so far

 Response.ContentType = "image/jpeg" 'output image instead

 Dim Text As String = "Submit" 'default text

 If Request.QueryString("Text") IsNot Nothing Then

    'Retrieve button text from a QueryString parameter

     Text = Server.UrlDecode(Request.QueryString("Text"))

 End If

 'Call the button image generator

   Dim bmp As Bitmap = DynaBtn.GenButton(Text)

 bmp.Save( _

     Response.OutputStream, _

     Imaging.ImageFormat.Jpeg)

 Response.End()

End Sub

Figure 4: The PreInit method of a standard ASPX page is suitable for rendering the dynamic button image.

 

The first line of Figure 4 ensures any HTML-related gunk is removed from the response stream. The second line specifies that this page will instead output a jpeg image.

 

The second block of code gets the button text from a QueryString parameter. If the Text parameter is not found in the QueryString, a default of Submit will be displayed as the button text.

 

The third block of code retrieves the button image from the GenButton method listed in Figure 2, which in turn calls the GenButton method of Figure 1. The final line (Response.End) aborts the rest of the normal page lifecycle because it s not needed.

 

The final piece of the puzzle is a reference to this special image-generating page from a content page (such as default.aspx; refer back to Figure 3 for the resulting image):

 

   ID="ImageButton1"

   runat="server"

   ImageUrl="~/DynBtn.aspx?Text=Log+In"

/>

 

Enhancing Configurability

Now what s going to happen when the customer requests that the button colors be changed? Well, you could simply change the hard-coded button defaults in Figure 2. Then you ll have to recompile and redeploy the application. In simple situations this can be a reasonable approach, but some software systems in some companies require more laborious deployment scenarios. This could be further complicated if you choose to deploy the DynaBtn class in its own assembly, which would improve cross-project reuse, but potentially adds an extra compilation and deployment step, as well.

 

Generally speaking, a better approach would be to ditch the code in Figure 2 and instead refactor those button defaults into the image generator page listed in Figure 4. To take it one step further, it would be better yet for the code to pull those defaults from the web.config file so that updates can be deployed without needing to recompile. Let s take a closer look at this approach.

 

First, add some custom default button values to the web.config:

 

 

   

   

   

   

   

   

 

 

Then modify the code DynBtn.aspx.vb code from Figure 4 to retrieve these default button values from the web.config file. Figure 5 shows how this is done. You might optionally choose to enhance this image server page even further by allowing custom button values to be passed via a QueryString (as is done with the button text).

 

'Imports System.Drawing

'Imports System.Web.Configuration.WebConfigurationManager

Protected Sub Page_PreInit(ByVal sender As Object, _

                          ByVal e As System.EventArgs) _

                          Handles Me.PreInit

 Response.Clear()

 Response.ContentType = "image/jpeg"

 Dim Text = "Submit" 'default text

 'retrieve button text from QueryString parameter

 If Request.QueryString("Text") IsNot Nothing Then

   Text = Server.UrlDecode(Request.QueryString("Text"))

 End If

 'retrieve default button values from web.config

 Dim sBackClr As String = AppSettings("DynaBtn_BackColor")

 Dim sForeClr As String = AppSettings("DynaBtn_ForeColor")

 Dim BackColor As Color = Color.FromName(sBackClr)

 Dim ForeColor As Color = Color.FromName(sForeClr)

 Dim PadH As Integer = AppSettings("DynaBtn_PadH")

 Dim PadV As Integer = AppSettings("DynaBtn_PadV")

 Dim FontName As String = AppSettings("DynaBtn_FontName")

 Dim FontSize As Integer = AppSettings("DynaBtn_FontSize")

 Dim font As Font = New Font(FontName, FontSize)

 'Call the button image generator

 Dim bmp As Bitmap = DynaBtn.GenButton( _

   Text, _

   BackColor, _

   ForeColor, _

   font, _

   PadH, _

   PadV)

 bmp.Save( _

   Response.OutputStream, _

   Imaging.ImageFormat.Jpeg)

 Response.End()

End Sub

Figure 5: This code is more configurable than the code in Figure 4 because it pulls default values from the web.config file instead of hard-coding them.

 

Now the colors, fonts, and padding of all buttons site-wide can be changed instantly from one central location (the web.config file) without needing to recompile anything (see Figure 6).

 


Figure 6: You can optionally apply different color schemes to different buttons.

 

Conclusion

The code accompanying this article can be quite useful as-is, but it should also be considered a great starting point for an even more powerful button-generation system. I can envision many potential enhancements to this system, such as adding colorful gradient backgrounds and fancy borders with 3-D effects. Further enhancements could include the ability to specify different categories of buttons, such as primary and secondary buttons with individually adjustable colors and shading. The only real limits are those of your imagination, so let your mind wander and see what you come up with. I d love to hear about any interesting enhancements you add.

 

C# and VB.NET source code accompanying this article is available for download.

 

Steve C. Orr is an ASPInsider, MCSD, Certified ScrumMaster, Microsoft MVP in ASP.NET, and author of Beginning ASP.NET 2.0 AJAX by Wrox. He s been developing software solutions for leading companies in the Seattle area for more than a decade. When he s not busy designing software systems or writing about them, he can often be found loitering at local user groups and habitually lurking in the ASP.NET newsgroup. Find out more about him at http://SteveOrr.net or e-mail him at mailto:[email protected].

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish