Sunday, September 23, 2007

Calculating the length of Text using GDI

I'd like to show a simple example of calculating the length of text which is very handy when building your own controls. This technique works with either version of the framework (desktop or compact).

Take the following control I designed below. Notice how the top line which contains the description is too long for the width of the screen space, so a "..." has been appended to the description. This makes much easier reading.


The code is very simple. Something like the following would need to be added to your OnPaint method of your user control class:



protected override void OnPaint(PaintEventArgs e)
{
Color fontColor;
int descriptionLength;
int periodsWidth;
int maxDisplayableDesc;
bool truncated;
Graphics grfx = e.Graphics;
int clientWidth =
this.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 0);

//Foreach item in your user control do the following:
string description = assignmentListItem.Description;
periodsWidth =
(int)(_grfx.MeasureString("... ", boldFont).Width);
descriptionLength = (int)(grfx.MeasureString(description, boldFont).Width);
maxDisplayableDesc = clientWidth - periodsWidth;
index = description.Length;
truncated = false;
if (descriptionLength +
(DRAWX_OFFSET * _grfx.DpiX / DESIGNPOINTSPERINCH)
> maxDisplayableDesc)
truncated = true;

while (descriptionLength +
(DRAWX_OFFSET * _grfx.DpiX / DESIGNPOINTSPERINCH) > maxDisplayableDesc)
{
description = description.Substring(0, index - 1);
index--;
descriptionLength =
(int)(_grfx.MeasureString(description.Substring(0, index - 1),
boldFont).Width);
}

if (truncated)
description = description + "...";

//Draw the description.
grfx.DrawString(description,
boldFont,
foreColor,
DRAWX_OFFSET * _grfx.DpiY / DESIGNPOINTSPERINCH,
itemTop + (DRAWY_OFFSET * _grfx.DpiY / DESIGNPOINTSPERINCH));

grfx.Dispose();
}


Of course as you can see the code above is massively cutdown and only focuses on the actual calculation of whether the text will fit within the screen space and if it doesn't, how many characters can we display before we run off the edge of the screen. This is assuming you are using a non-proportional font which is what the code was designed to work with. In fact an improvement would be to check what the typeface font is before doing the character-by-character calculation.