Generate Dynamic Buttons

Create Attractive Image Buttons Instantly at Run Time

Steve C Orr

October 30, 2009

9 Min Read
ITPro Today logo

ControlFreak

LANGUAGES:VB.NET | C#

ASP.NETVERSIONS: 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 theirugly gray interface renders them fairly useless for design-conscious Web sites.For this reason, most Web sites tend to use the ImageButton control much moreoften than the Button control. Of course, the main problem with ImageButtons isthe need to create and maintain all those images. And if your customersare like most, they likely change their minds several times during thedevelopment process about exactly which colors they d like to see on theirbuttons. Such innocently na ve requests can generate lots of rework that tendsto suck away time from other important development tasks. They don t understandhow simply changing a color or two can take so much work and trying toexplain it to them can end up sounding whiney and unprofessional.

 

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

 

Creating the Image

At the heart of every image button is an image. TheDynaBtn class listed in Figure 1 can create just such an image dynamically atrun time. Simply feed the GenButton function some basic parameters (for thetext to be displayed, the colors to be used, and the desired margins) and itwill return a bitmap that matches yourspecifications. This class could be compiled into its own DLL for optimalreuse, or it could simply be included in the App_Code folder of an ASP.NET Webapplication.

 

Imports System.Drawing

Imports System.Drawing.Imaging

Public Class DynaBtn

 Public Shared FunctionGenButton( _

   ByVal text As String, _

   ByVal backColor AsColor, _

   ByVal foreColor AsColor, _

   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 sizeneeded for the specified text & font

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

   'add some size for themargins

   Dim width As Integer =Convert.ToInt32( _

       size.Width + (PadH* 2))

   Dim height As Integer =Convert.ToInt32( _

       size.Height + (PadV* 2))

   'now recreate the imageat the correct size

   bmp = New Bitmap(width,_

                    height, _

                    PixelFormat.Format32bppRgb)

   g =Graphics.FromImage(bmp)

   'fill it with thebackground color

   Dim brush As NewSolidBrush(backColor)

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

   'now draw the text withthe specified forecolor

   Dim brush2 As NewSolidBrush(foreColor)

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

   Return bmp

 End Function

End Class

Figure 1: TheDynaBtn class can be used to dynamically generate ImageButton images as neededat run time.

 

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

 

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

 

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

 

Figure 2 displays an optional overloaded version of theGenButton function. This overloaded GenButton function simply calls theoriginal GenButton function (listed in Figure 1) after setting some hard-codeddefault parameters. Hard-coding defaults in this way can be acceptable in somesituations, although later in this article we ll explore preferable techniquesfor configuring them.

 

Public Shared Function GenButton( _

   Optional ByVal text AsString = "Submit") As Bitmap

   'create defaults

   Dim PadH As Integer = 5

   Dim PadV As Integer = 5

   Dim font As Font = NewFont("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: Thisoverloaded version of the GenButton function simplifies the parameter list atthe expense of some flexibility.

 

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

 

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

 

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

 


Figure 3: This is a basic buttongenerated dynamically at run time by the GenButton function of the DynaBtnclass.

 

Displaying the Image

For an image to be displayed on a Web page, it must be referencedby 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 andImageButton controls.

 

A Web page that contains an image requires at least twoseparate browser requests: one for the textual page content and one for theimage. This necessitates a separate handler to deal with the separate imagerequest. Standard Web forms (ASPX pages) and HTTP handlers are both reasonablesolutions for responding to such requests. An HTTP handler can be slightly moreefficient, 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 canevade almost as much of the unnecessary HTML handling routines. The DynaBtnclass 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 buttonimages, first add a new Web form to an ASP.NET Web application. Choose a shortunique filename such as DynBtn.aspx. You can remove all the HTML from this Webform because this special page will be emitting an image instead of HTML. Allthe real work will happen in the code-behind for this page.

 

It s best to render the image as early as possible in thepage lifecycle to efficiently evade most of the Web page s superfluous HTMLhandling routines. In this case, the PreInit event is adequate for this goal (Figure4 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() 'Deleteany HTML buffered so far

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

 Dim Text As String ="Submit" 'default text

 IfRequest.QueryString("Text") IsNot Nothing Then

    'Retrieve button textfrom a QueryString parameter

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

 End If

 'Call the button imagegenerator

   Dim bmp As Bitmap= DynaBtn.GenButton(Text)

 bmp.Save( _

     Response.OutputStream, _

     Imaging.ImageFormat.Jpeg)

 Response.End()

End Sub

Figure 4: ThePreInit method of a standard ASPX page is suitable for rendering the dynamicbutton image.

 

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

 

The second block of code gets the button text from aQueryString 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 fromthe GenButton method listed in Figure 2, which in turn calls the GenButtonmethod of Figure 1. The final line (Response.End) aborts the rest of the normalpage lifecycle because it s not needed.

 

The final piece of the puzzle is a reference to thisspecial image-generating page from a content page (such as default.aspx; referback 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 customerrequests that the button colors be changed? Well, you could simply change thehard-coded button defaults in Figure 2. Then you ll have to recompile andredeploy the application. In simple situations this can be a reasonableapproach, but some software systems in some companies require more laboriousdeployment scenarios. This could be further complicated if you choose to deploythe 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 ditchthe code in Figure 2 and instead refactor those button defaults into the imagegenerator page listed in Figure 4. To take it one step further, it would bebetter yet for the code to pull those defaults from the web.config file so thatupdates can be deployed without needing to recompile. Let s take a closer lookat this approach.

 

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

 

 

   

   

   

   

   

   

 

 

Then modify the code DynBtn.aspx.vb code from Figure 4 toretrieve these default button values from the web.config file. Figure 5 showshow this is done. You might optionally choose to enhance this image server pageeven 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 textfrom QueryString parameter

 IfRequest.QueryString("Text") IsNot Nothing Then

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

 End If

 'retrieve default buttonvalues 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 = NewFont(FontName, FontSize)

 'Call the button imagegenerator

 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: Thiscode is more configurable than the code in Figure 4 because it pulls defaultvalues from the web.config file instead of hard-coding them.

 

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

 


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

 

Conclusion

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

 

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

 

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

 

 

 

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like