After writing several websites with custom buttons. I’ve had it with having to create images for each button that has a different text!
If you feel the same way then you’ll love this solution. With the code below you’ll be able to create a button.aspx page that takes a “t” url query parameter where you can specify the text and it will return the desired image. Here are some usage examples:
“http://siteurl.com/button.aspx?t=Yes!” will give you:
“http://siteurl.com/button.aspx?t=BACK&m=t” will give you:
“http://siteurl.com/button.aspx?t=CONTINUE” will give you:
Even though the links to the image are not your usual *.png or *.jpg, the button.aspx page returns an image (content type image/x-png or image/jpeg) so it is OK to do the following in your aspx code:
<asp:ImageButton runat="server" ID="btnFormBack" ImageUrl="button.aspx?t=Continue" />
OR
<a href="targeturl.html"><img src="button.aspx?t=Continue" /></a>
Pretty cool ha!
Well, and now to the code. This is your button.aspx file:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="button.aspx.cs" Inherits="controls_button" %> <%@ OutputCache VaryByParam="m;t" Duration="9123123" %>
And your button.aspx.cs file:
public partial class controls_button : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { var text = this.Request.QueryString["t"]; if (string.IsNullOrEmpty(text)) throw new ApplicationException("The text url parameter must be specified"); var sMirror = this.Request.QueryString["m"]; bool mirror = (!string.IsNullOrEmpty(sMirror) && sMirror == "t"); var rightImageWidth = 10; // in pixels var imageHeight = 42; var topPadding = 11; // top and bottom padding in pixels var sidePadding = 10; // side padding in pixels var textBrush = new SolidBrush(Color.White); var font = new Font("Arial Black", 11); //-------- Calculate the text's width // this graphics and bitmap object is just temporary. I could not // find a way to calculate the text' width witout having one. var bitmap = new Bitmap(300, 300); var graphics = Graphics.FromImage(bitmap); var textSize = graphics.MeasureString(text, font); bitmap.Dispose(); graphics.Dispose(); //-------- Create the graphics object var bitmapWidth = sidePadding * 2 + (int)textSize.Width; bitmap = new Bitmap(bitmapWidth, imageHeight); //bitmap = new Bitmap(500, 40); graphics = Graphics.FromImage(bitmap); // Draw the background var leftImage = System.Drawing.Image.FromFile(this.Server.MapPath("~/resources/button-left.png")); var rightImage = System.Drawing.Image.FromFile(this.Server.MapPath("~/resources/button-right.png")); graphics.DrawImage(leftImage, 0, 0, bitmapWidth - rightImageWidth, imageHeight); graphics.DrawImage(rightImage, bitmapWidth - rightImageWidth, 0, rightImageWidth, imageHeight); // These disposes are necessary, otherwise the files get locked leftImage.Dispose(); rightImage.Dispose(); if (mirror) bitmap.RotateFlip(RotateFlipType.RotateNoneFlipX); // Draw the text graphics.DrawString(text, font, textBrush, sidePadding, topPadding); //-------- Serve the Image this.Response.ContentType = "image/x-png"; // The line below breaks on the production and development servers // (it does not break on my computer). I was getting the following // vague exception "A generic error occurred in GDI+". I found this // post that showed // me the work around http://aspalliance.com/319 . In short it says // that some image formats (like Png) require a seekable stream when // saving. The Response.OutputStream is not seekable so we // have to use a MemoryStream as an intermediary. //bitmap.Save(this.Response.OutputStream, ImageFormat.Png); var memStream = new System.IO.MemoryStream(); bitmap.Save(memStream, ImageFormat.Png); memStream.WriteTo(this.Response.OutputStream); // Some cleanup, not sure if it is all needed this.Response.End(); memStream.Dispose(); graphics.Dispose(); bitmap.Dispose(); } }
And you also need to have these images in the ~/resources folder of your website. If you want to have them in another folder, update the .cs code.
~/resources/button-left.png :
~/resources/button-right.png :
Enjoy!