Download Project Source Code
Download Additional LCD Bitmaps
Introduction
Sometimes we just want to give our WinForms applications a new look. And sometimes giving our application a new look is complex, and other times it's easy.
This article presents a very simple user control that emulates the look of an LCD display.
The LCDDisplay User Control
Listing 1 shows the code for my LCDDisplay user control. As you can see, it's a pretty simple control.
You call the SetImage() method to provide the control with a bitmap, and a string that maps characters to parts of the bitmap. For example, consider the following bitmap.
This bitmap contains 13 characters. The character list string in this case could be ". 0123456789:". This string tells the control how many characters are in the bitmap, and how to map those characters. Note that each character in the bitmap must be the same width for this to work correctly.
You can then set the Text property and the control will attempt to map the characters in the Text property to the bitmap. If any character does not exist in the character list, that character will be represented by the first character in the bitmap. In the example above, I've made the first character an invalid character that would alert you to the fact that a character could not be mapped. In my character list string, I mapped a period to the first character. This is not really important. I just used a character that is not otherwise supported by the string.
Listing 1: The LCDDisplay User Control
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SoftCircuits
{
public partial class LCDDisplay : UserControl
{
protected Image _image;
protected string _charList;
/// <summary>
/// Text to display in the control. Characters that do not match any in
/// the character list will be displayed using the first character in
/// the character list.
/// </summary>
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
Refactor();
}
}
public LCDDisplay()
{
InitializeComponent();
// Initialize members
_image = null;
_charList = null;
Text = String.Empty;
}
/// <summary>
/// Sets the current image and character map. The number of characters
/// in charList must exactly match the number of digits in the bitmap
/// for characters to be displayed properly.
/// </summary>
/// <param name="image"></param>
/// <param name="charList"></param>
public void SetImage(Image image, string charList)
{
_image = image;
_charList = charList;
Refactor();
}
/// <summary>
/// Redraws and possibly resizes the control based on the current
/// settings.
/// </summary>
private void Refactor()
{
// Don't do anything if no character image
if (_image == null || _charList == null)
return;
// Resize control to fit image
if (_image.Width > 0 && _image.Height > 0 && _charList.Length > 0 && Text.Length > 0)
SetClientSizeCore(Text.Length * _image.Width / _charList.Length, _image.Height);
// Redraw
Invalidate();
}
// Paints control
private void LCDDisplay_Paint(object sender, PaintEventArgs e)
{
// Don't do anything if no character image
if (_image == null || _charList == null)
return;
// Determine dimensions of each character cell
int cellWidth = _image.Width / _charList.Length;
Rectangle rect = new Rectangle(0, 0, cellWidth, _image.Height);
// Draw cells one at a time
foreach (char c in Text)
{
// Get offset for this character
int cx = Math.Max(_charList.IndexOf(c), 0) * cellWidth;
// Draw character cell
e.Graphics.DrawImage(_image, rect, cx, 0, cellWidth,
_image.Height, GraphicsUnit.Pixel);
// Bump position
rect.Offset(cellWidth, 0);
}
}
}
}
The code that brings everything together is in the Paint event handler. This code starts by determining the size of each character in the bitmap. It then loops through each character in the Text property, mapping them to the bitmap. For each character, it displays only the corresponding part of the bitmap to the current location in the control's window.
I should also point out that the control will resize itself so that it will exactly fit the characters displayed. This gives the control a much cleaner look, but it can also cause problems when a control decides what size it wants to be. If this doesn't work for you, just remove the code in the Refactor() method that resizes the control.
I should also note that I set the user control's DoubleBuffered property to true. Although it uses a few more resources, this is a simple way to prevent the paint routine from flickering.
Using the Control
My demo project sets a timer and then updates the Text property of the user control to the current time. The effect is a digital clock that maintains the current time.
Listing 2 shows the bulk of the code from my demo project's main form. You can see the code initializes the LCD control in the Form's Load event. It then updates the control's Text property whenever the Timer control raises the Tick event.
Listing 2: The Demo Projects Form
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
Image img = Image.FromFile("Digits1Grn.bmp");
lcdDisplay1.SetImage(img, ". 0123456789:");
UpdateTime();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
UpdateTime();
}
private void UpdateTime()
{
lcdDisplay1.Text = DateTime.Now.ToString("hh:mm:ss");
}
}
I should point out that the demo project loads the bitmap file from the current directory, which will initially be the Debug subdirectory. So that is where I've placed the sample bitmap. As you modify the project and/or move files around, you'll need to ensure your code can find this file.
Conclusion
That's about all there is to it. I'm including an additional download of several LCD bitmaps that I created. You can use them as-is, or modify them to contain the characters and appearance you need.
Just remember, when you pass the image to the SetImage() method, make sure the character list string has exactly one character for each character in the bitmap. The control uses this information to correctly display the characters.
End-User License
Use of this article and any related source code or other files is governed
by the terms and conditions of
.
Author Information
Jonathan Wood
I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.