I am using pixels as the unit for my font. In one place, I am performing a hit test to check if the user has clicked within the bounding rectangle of some text on screen. I need to use something like MeasureString
for this. Unfortunately, the code doing the hit test is deep within a library which does not have access to a Graphics
object or even a Control
.
How do I get the bounding box of a string given the font without using the Graphics
class? Why do I even need a Graphics
object when my font is in pixels?
If you have a reference to System.Windows.Forms, try using the TextRenderer class. There is a static method (MeasureText) which takes the string and font and returns the size. MSDN Link
TextRenderer.DrawText(e.Graphics,
jp2code 2012-10-03 19:01
DrawText
method's first parameter is Graphics. Am I missing something - jp2code 2012-10-05 13:31
WindowsGraphicsCacheManager
. The manager has a static MeasurementGraphics
property which gets inited on its first use. It does this by creating a graphics from the device context with a PInvoke to the gdi32.dll using this constructor. NerdFury's answer eventually uses this constructor and of course the Graphics isn't cached but otherwise they're the sam - Conrad Frix 2013-02-26 20:58
System.Windows.Forms
just to measure a string, which might have nothing to do with forms - Dave Cousineau 2018-08-23 21:36
You don't need to use the graphics object that you are using to render to do the measuring. You could create a static utility class:
public static class GraphicsHelper
{
public static SizeF MeasureString(string s, Font font)
{
SizeF result;
using (var image = new Bitmap(1, 1))
{
using (var g = Graphics.FromImage(image))
{
result = g.MeasureString(s, font);
}
}
return result;
}
}
It might be worthwile, depending on your situation to set the dpi of the bitmap as well.
MeasureString
method in @NerdFury answer will give a higher string width than expected.Additional info you can find here. If you want to measure only the physical length please add this two lines :
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
result =
g.MeasureString(measuredString, font, int.MaxValue, StringFormat.GenericTypographic);
This example does great job of illustrating the use of FormattedText. FormattedText provides low-level control for drawing text in Windows Presentation Foundation (WPF) applications. You can use it to measure the Width of a string with a particular Font without using a Graphics object.
public static float Measure(string text, string fontFamily, float emSize)
{
FormattedText formatted = new FormattedText(
item,
CultureInfo.CurrentCulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(fontFamily),
emSize,
Brushes.Black);
return formatted.Width;
}
Include WindowsBase and PresentationCore libraries.
This may not be but a repeat of others, but my problem was the unwanted Graphics object as well. After listening to the above frustrations I simply tried:
Size proposedSize = new Size(int.MaxValue, int.MaxValue);
TextFormatFlags flags = TextFormatFlags.NoPadding;
Size ressize = TextRenderer.MeasureText(content, cardfont, proposedSize, flags);
(where 'content' is the string to measure and cardfont the font it is in)
... and was in luck. I could use the result to set the width of my column in VSTO.