Determine width of text (in pixels) on Windows screen

Started by
4 comments, last by Erik Rufelt 15 years, 4 months ago
Hi all, I am currently struggling to figure out how to determine how wide a string of text is on the screen, particularly when I change resolutions in my Win32 application. The reason I want to determine how wide a string will be, particularly between resolution changes, is that I want the strings to be of the same length relative to the size of the screen, regardless of what resolution the user picks. Note: Using C++ MSVC 6.0 and Win32 application. Here's how I create the font handle (I do this once):

   m_FontHandle = LoadResourceFont(&m_hFont, 
		  (LPCTSTR)(MAKEINTRESOURCE(IDR_RT_FONT_1)), 
		  "RT_FONT", "Font 1", 
		  -MulDiv(32, GetDeviceCaps(hdc, LOGPIXELSY), 72));
Here is how I try to determine the width (in pixels) of the text that will be displayed: "Calculate Width":

float GetTextWidth( const std::string& text )
{
   HDC hdc = GetDC(NULL);

   SelectObject(hdc, &m_hFont);

   RECT screenRect;
   ZeroMemory(&screenRect, sizeof(RECT));
   GetClientRect(m_g->GetHWND(), &screenRect);

   UINT screenWidth = screenRect.right - screenRect.left;

   RECT rect;
   DrawText(hdc, text.c_str(), text.length(), &rect, DT_CALCRECT);

   // float width = ????
.
.
.
}
I've tried several different ways to calculate the width, to no success. When I count the pixels wide for the text, it never came up to be the same as the formula calculation I did in my code. Has any one tried this before? Any help would be much appreciated! roger_hq
_____________________________http://www.deepbluefuture.com"Set Phasers to neuter...""2+2=5 for sufficiently large values of 2."
Advertisement
There is a function for this purpose, GetTextExtentPoint32. Check the following page for further details:
http://msdn.microsoft.com/en-us/library/ms534223(VS.85).aspx

EDIT: Though your function with DrawText should also do it... not sure why you're getting the wrong results. How do you check the correct results?
Do you actually count the pixels on the screen, and they don't match the rect?
Correct - I take a screen shot, and count the pixels. I compare that to the value my application logs for the calculated width of the string, and they never come out the same. There seems to be some kind of discrepancy either with the conversion from logical units to pixels or how I'm interpreting the information that comes back from GetTextExtentPoint32().
_____________________________http://www.deepbluefuture.com"Set Phasers to neuter...""2+2=5 for sufficiently large values of 2."
Quote:Original post by roger_hq
Correct - I take a screen shot, and count the pixels. I compare that to the value my application logs for the calculated width of the string, and they never come out the same. There seems to be some kind of discrepancy either with the conversion from logical units to pixels or how I'm interpreting the information that comes back from GetTextExtentPoint32().


What's the difference? Is it just a couple of pixels (bigger or smaller?) or is it a significant amount?

I imagine the difference is because you're calling GetDC(NULL) and then (presumably) drawing to a different DC, is that right? GetDC(NULL) returns the DC for the screen, and I'm not sure whether that DC would support ClearType. There is a difference in the number of pixels a piece of text takes when ClearType is turned on compared to when it's off (though it's only small).

In any case, I would recommend you try using DrawText(..., DT_CALCRECT) on the DC that you're actually drawing to in the end. It seems to me replacing GetDC(NULL) with GetDC(m_g->GetHWND()) should do the trick?

Just as an aside, is there any reason why you're using VC++ 6? Visual Studio 2008 Express Edition can be downloaded for free... the only limitation that would affect most people is a lack of the ability to integrate with source control, and possibly lack of MFC.
The difference is actually quite significant. When the calculation comes back from DrawText() or GetTextExtentPoint32(), in one example, I get a value of 134. When I count the pixels on the screen, it is actually 609 pixels wide. It's a pretty major difference, which makes me wonder if I'm interpreting the value coming back from DrawText() / GetTextExtentPoint32() correctly.

Also note, that I am using a LOGFONT structure, which I set the height/width of the log font before I select it before each measurement:

   logFont.lfCharSet = ANSI_CHARSET;   logFont.lfHeight = 100;   SelectObject(hdc, &m_hFont);   GetObject(m_hFont, sizeof(LOGFONT), &logFont);


Not sure if this makes any difference, I suspect not.

I also did as you suggested and changed the code to use the DC I should be (oops!), and it didn't seem to have any affect.

Any other thoughts as to why the two values would be so far off?
_____________________________http://www.deepbluefuture.com"Set Phasers to neuter...""2+2=5 for sufficiently large values of 2."
When selecting the font you're not supposed to do &hFont, just hFont, to SelectObject. Also, if it still doesn't work, check return-values of all your functions, and check for errors. Both for SelectObject and for DrawText.

This topic is closed to new replies.

Advertisement