# D3DXFONT and length of string

This topic is 4044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have created a font using D3DXCreateFont, and I am paaing a height and width variable. I then use DrawText, and I am passing the number of characters with str.length() I would like to be able to get the length of the string in pixels on the screen, not only for the Rect but also for adding more text to the same line. Using str.width() * height doesnt seem to work right, because it seems that some characters different width than other characters. How can I get this length?

##### Share on other sites
This is whatI do - maybe there is a better way.

After calling D3DXCreateFont(), I get the HDC of the font and use that to get an array of widths for characters from ' ' to '~'. Store that along with the font pointer for use in figuring out string widths in pixels.

Here is some simplified code

D3DXCreateFontIndirect(m_pDevice, &(f->desc), &(f->font));f->font->PreloadCharacters(' ', '~');HDC hdc = f->font->GetDC(); if (!GetCharWidth32(hdc, ' ', '~', f->widths)) {  ABC w[95];  GetCharABCWidths(hdc, ' ', '~', w);  for (int i = 0; i < 95; ++i) f->widths = w.abcA + w.abcB + w.abcC;}

GetCharWidth32() only works for non-true type.
GetCharABCWidths() only works for true type.

##### Share on other sites
ID3DXFONT's DrawString method returns a RECT describing the area the text was drawn in. This is useful for calculating string widths.

If you want to just calculate the width without actually drawing, you can pass a CALCRECT flag to the function, that makes it skip drawing and just return the RECT it would have drawn to. Check the DX Docs for more information.

Hope this helps.

##### Share on other sites
ID3DXFont::DrawText supports the DT_CALCRECT format-flag, which causes the function not to render any text, but calculate the minimum-bounding-RECT and return it.

##### Share on other sites
I recall that there was some issues around DrawText / DT_CALCRECT and how it handles spaces. Sometimes the space character would be counted with a width of 0. I don't recall the exact cases - its been a while. Possibly its even fixed now :p

##### Share on other sites
This is all I can find in the docs on DT_CALCRECT

"Determines the width and height of the rectangle. If there are multiple lines of text, ID3DXFont::DrawText uses the width of the rectangle pointed to by the pRect parameter and extends the base of the rectangle to bound the last line of text. If there is only one line of text, ID3DXFont::DrawText modifies the right side of the rectangle so that it bounds the last character in the line. In either case, ID3DXFont::DrawText returns the height of the formatted text but does not draw the text."

I dont understand how to use this. It does not draw the text? Do I call it twice then? Or do I say Rect rct=font->DrawText(/my,params,and,stuff,DT_CALCRECT)? I tried those 2 ways but no luck yet :) Can someone please show me an example of its use?

 I want to thank you madox for your solution also. I am still looking at it, but there are some things in it that I don't yet understand, and I am learning its different parts also :)

##### Share on other sites
With the DT_CALCRECT flag set it will not draw the text, you have to make another call with out the flag set to draw it.

Ideally you use the version with DT_CALCRECT before you are ready to render, to ensure text is spaced out appropriately so it doesn't overlap, and making sure it doesn't go off screen.

For example:
I have used this to ensure text doesn't overlap or go off screen in a window that displays images with their name. Since the images may be bigger or smaller than the width of the text I need to know the texts width to make sure things are spaced out.

##### Share on other sites
OK thanks. This dosen't seem to be what im looking for then. My text and string length changes during runtime. I need to know the length of the text in real time. I did try calling it twice during my render, but just got a blank screen.I can't find an example of it anywhere. I think I will use madox's method, I just need to break it down a little. I have a bad habit of having to understand every little thing before I use somthing :)
Thanks everybody.

##### Share on other sites
Quote:
 Original post by oldskoolPunkOK thanks. This dosen't seem to be what im looking for then. My text and string length changes during runtime. I need to know the length of the text in real time. I did try calling it twice during my render, but just got a blank screen.I can't find an example of it anywhere. I think I will use madox's method, I just need to break it down a little. I have a bad habit of having to understand every little thing before I use somthing :)Thanks everybody.
You can still call it at runtime. Something like this (Semi-psuedo-code):

RECT rc;pFont->DrawText(&rc, ..., DT_CALCRECT); // Might want DT_SINGLELINE too// rc now contains the size of the text. Width in pixels is rc.right-rc.left// Adjust rect if neededpFont->DrawText(&rc, ..., 0); // Actually draw the text this time

##### Share on other sites
Thanks, man, it works!
I tried this before, and it didn't work (no text was displayed). Well, you have to fill rect.top and rect.left , I wasn't doing this.

Thanks Evil Steve and everyone else.

##### Share on other sites
Quote:
 Original post by madoxAfter calling D3DXCreateFont(), I get the HDC of the font and use that to get an array of widths for characters from ' ' to '~'. Store that along with the font pointer for use in figuring out string widths in pixels.

To be a little bit picky, this will not always be accurate. Sometimes certain pairs of characters will be drawn closer together than other pairs, and their total width will therefore be different to the sum of the two characters - this is called kerning. It just makes the text look a little nicer. For example, many fonts have kerning between the letters 'l' and 'w' - because the curly bit at the bottom of the 'l' can fit under the angled first line of the 'w'.

It certainly sounds like DT_CALCRECT is the way to go anyway, but I thought I'd mention this as making an array as suggested would be slightly inaccurate. (Not by much, granted).