Measure string height RRS feed

  • Question

  • Hello all

    I need to draw a string with specific font and sizes.

    For this i have to get first the sizes: 

    SizeF s = g.MeasureString(text, font); but this sizes are bigger then the one that i used to choose the font.

    For compact framework i don't see other method to measure the string.

    How can i get the exact height of the Text that i want to Draw ? 

    Tank's in advance.

    Just compile it !
    Thursday, December 30, 2010 10:56 AM


All replies

  • You already have it:

    SizeF s = g.MeasureString(text, font);


    This posting is provided "AS IS" with no warranties, and confers no rights.
    • Marked as answer by Bin-ze Zhao Tuesday, January 4, 2011 6:05 AM
    • Unmarked as answer by fant20 Tuesday, January 4, 2011 7:14 AM
    Thursday, December 30, 2010 4:39 PM
  • Hi Fant20,

    In .NET CF have "MeasureString()" Method in Graphics class. You can access it using Graphics class object.

    Here is listed Graphics.MeasureString Method is supported by .NET CF.

    Hope it helps

    - Pavan Pareta [MCTS - Windows Mobile 5.0] If you find my post is helpful for you then mark as a answer and vote it.
    • Marked as answer by Bin-ze Zhao Tuesday, January 4, 2011 6:05 AM
    • Unmarked as answer by fant20 Tuesday, January 4, 2011 7:14 AM
    Monday, January 3, 2011 4:47 AM
  • Hi all,

    Yes i know that it is this method and i had no difficulties to get the graphics object, but it gives me not very good values. For instance for text height in pixel 44, the MeasureString gives me the value 53. But i need more accurate values.

    Can someone help me how to do this in CF3.5 ?


    Just compile it !
    Monday, January 3, 2011 7:36 AM
  • Hi Fant20,


    Make sure that your font size is as you required because the thing is that Measure String method consider font size whatever you have assigned to method to calculate the height and width.


    Hope it helps.

    - Pavan Pareta [MCTS - Windows Mobile 5.0] If you find my post is helpful for you then mark as a answer and vote it.
    Monday, January 3, 2011 1:59 PM
  • yes, this is checked... the measure size is done with the same font. 
    Just compile it !
    Monday, January 3, 2011 3:13 PM
  • Why do you believe it's 44 and not 53 as measured?
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, January 3, 2011 11:42 PM
  • Ilya, i'm working on different devices with different resolutions, so to have a less or more rapports for my own GUI components i create them according to the current DPI from the formula:  

     float size = (float)(height * 72 / DpiX);

    height is the size of the client area in pixels in my case 44.

    and get the font from :
    returnFont = new Font("Tahoma", size, fontstyle);

    now if i get from the measured string the dimensions and draw that rectangle that i see that these rectangle have the height of 53 even if the entire text fits in the rectangle with height 44(i did here some tests, used the letters from limits like "gpLT").
    Why i get the size of 53 i cannot understand. 
    I did another test:
    SizeF s = g.MeasureString(text, font);
    g.DrawString( text, font, new SolidBrush(foreColor), new Rectangle(0, 0, (int)s.Width, (int)s.Height));
    on a bitmap with the same sizes and also choosed the text from limits from upper. After i looked trough all pixels and eliminated the rows that don't have the color - "foreColor". The remaining object have the dimension of 44.

    I hope that this is more clear what i did and how i get here.
    Tx for trying help me.

    Just compile it !
    Tuesday, January 4, 2011 7:28 AM
  • There are two other ways to measure the text height.


    Use the GDI call GetTextMetrics


    NativeMethods.TEXTMETRIC metric = new NativeMethods.TEXTMETRIC();
    				if (Environment.OSVersion.Platform == PlatformID.WinCE)
    					IntPtr hdc = gfx.GetHdc();
    					IntPtr hFont = font.ToHfont();
    					IntPtr oldFont = NativeMethods.SelectObject(hdc, hFont);
    					NativeMethods.GetTextMetrics(hdc, out metric);
    					NativeMethods.SelectObject(hdc, oldFont);
    					IntPtr hdc = gfx.GetHdc();
    					IntPtr hFont = font.ToHfont();
    					IntPtr oldFont = DesktopNativeMethods.SelectObject(hdc, hFont);
    					DesktopNativeMethods.GetTextMetrics(hdc, out metric);
    					DesktopNativeMethods.SelectObject(hdc, oldFont);
    				//int tmHeight = (int)Math.Round(font.Size * 96f / 72f);
    				int tmHeight = metric.tmHeight;


    Or use the DrawText function with the CALCRECT flag...


    NativeMethods.DrawText(hdc, info.Name, info.Name.Length, ref textRect, NativeMethods.DrawTextFlags.DT_CALCRECT | NativeMethods.DrawTextFlags.DT_CENTER | NativeMethods.DrawTextFlags.DT_VCENTER | NativeMethods.DrawTextFlags.DT_SINGLELINE); // measure the trace name

    You will have to import these functions yourself and corresponding flags, structs.  MeasureString surely uses one of these APIs.  I believe the reason I use DrawText is to handle vertically centered text, or perhaps text with multiple lines which the MeasureString method does not handle correctly (otherwise, I'm sure I wouldn't have gone through the trouble here)


    		public static extern bool GetTextMetrics(IntPtr hdc, out TEXTMETRIC lptm);
    public struct TEXTMETRIC
    			public int tmHeight;
    			public int tmAscent;
    			public int tmDescent;
    			public int tminternalLeading;
    			public int tmExternalLeading;
    			public int tmAveCharWidth;
    			public int tmMaxCharWidth;
    			public int tmWeight;
    			public int tmOverhang;
    			public int tmDigitizedAspectX;
    			public int tmDigitizedAspectY;
    			public char tmFirstChar;
    			public char tmLastChar;
    			public char tmDefaultChar;
    			public char tmBreakChar;
    			public byte tmItalic;
    			public byte tmUnderlined;
    			public byte tmStruckOut;
    			public byte tmPitchAndFamily;
    			public byte tmCharSet;
    [Flags] // from wingdi.h
    		public enum DrawTextFlags : uint
    			DT_TOP = 0x00000000,
    			DT_LEFT = 0x00000000,
    			DT_CENTER = 0x00000001,
    			DT_RIGHT = 0x00000002,
    			DT_VCENTER = 0x00000004,
    			DT_BOTTOM = 0x00000008,
    			DT_WORDBREAK = 0x00000010,
    			DT_SINGLELINE = 0x00000020,
    			DT_EXPANDTABS = 0x00000040,
    			DT_TABSTOP = 0x00000080,
    			DT_NOCLIP = 0x00000100,
    			DT_EXTERNALLEADING = 0x00000200,
    			DT_CALCRECT = 0x00000400,
    			DT_NOPREFIX = 0x00000800,
    			DT_INTERNAL = 0x00001000,
    			DT_EDITCONTROL = 0x00002000,
    			DT_END_ELLIPSIS = 0x00008000,
    			DT_RTLREADING = 0x00020000,
    			DT_WORD_ELLIPSIS = 0x00040000
    		public static extern int DrawText(IntPtr hdc, String str, int nCount, ref RECT rect, DrawTextFlags uFormat);
    public struct RECT
    		public static RECT GetRect(Rectangle r)
    			RECT temp;
    			temp.Left = r.Left;
    			temp.Right = r.Right;
    			temp.Top = r.Top;
    			temp.Bottom = r.Bottom;
    			return temp;
    		public int Left;
    		public int Top;
    		public int Right;
    		public int Bottom;
    		public int Width
    				return Right - Left;
    		public int Height
    				return Bottom - Top;
    		public void Translate(int x, int y)
    			Left += x;
    			Right += x;
    			Top += y;
    			Bottom += y;
    		public void Inflate(int width, int height)
    			Left -= width;
    			Top -= height;
    			Right += width;
    			Bottom += height;
    		public void Extend(int width, int height)
    			Right += width;
    			Bottom += height;
    		public bool IntersectsWith(Rectangle rect)
    			return ((((rect.X < (this.Right)) && (this.Left < (rect.Right))) && (rect.Y < (this.Bottom))) && (this.Top < (rect.Bottom)));
    		public RECT(int left, int top, int right, int bottom)
    			Left = left;
    			Top = top;
    			Right = right;
    			Bottom = bottom;

    Give them a try, Good luck


    Tuesday, January 4, 2011 4:05 PM
  • Just looking at my code, GetTextMetrics doesn't seem to be what you want, because it measures maximum possible,  I believe I'm using it when I need to know what it could be, when I don't know what the text will be.  On the other hand, in my other cases DrawText with CALCRECT doesn't seem to give me any less height than just multiplying by the resolution over 72, but instead is usually larger.  I'm pretty sure that MeasureString uses this function anyway.

    Hmm... are you sure MeasureString doesn't work?  I know I've run into issues before with measuring exact string sizes and it can be difficult.

    Tuesday, January 4, 2011 4:16 PM
  • OK, I see...

    What if you use DrawString() overload which does not clip the output to the preset rectangle?

    g.DrawString( text, font, new SolidBrush(foreColor), 0.0, 0.0);

    How about margins and padding?

    What is the actual font and font size created (your settings might be overridden based on available fonts and sizes).

    BTW, I'm pretty sure MeasureString() does what it suppose to do.

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Tuesday, January 4, 2011 5:19 PM
  • You could PInvoke GDI fn GetTextExtenPoint32(). It gives pretty accurate coverage of a string using the font selected in the dc.
    [SureCop:Phone Thief's worst nightmare!!]
    • Marked as answer by Bin-ze Zhao Friday, January 7, 2011 7:13 AM
    Tuesday, January 4, 2011 5:36 PM
  • Thank you for sugestions, i will try and i will post the results. :)
    Just compile it !
    Wednesday, January 5, 2011 8:10 AM