Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

? GetTextExtent Returns Unexpected Sizes

192 views
Skip to first unread message

Alec S.

unread,
Dec 17, 2008, 5:48:36 PM12/17/08
to
Blerg, I've got another problem.

I'm trying to set the widths of the headers in my list control myself since
LVSCW_AUTOSIZE_USEHEADER has "special features" that I don't like.

Some end up a little too big, and others a little too small. Here's the basic
code I'm using in the list control:

CString str = GetColumnName(this, nCol); // Retrieve header text
CDC* dc = m_Header.GetDC(); // Get a DC from the header
CSize size = dc->GetTextExtent(str); // Calculate text width
int width = size.cx; // Store width of text string
SetColumnWidth(nCol, width); // Set column width

I thought that maybe it's because GetTextExtent returns logical units, so I
tried LPtoDP, but that did not change the numbers. GetOutputTextExtent gives the
same numbers as GetTextExtent. I also tried DrawText(., DT_CALCRECT), but that
gave the same-incorrect-numbers as well.


As you can see in the attached screencap, "foobarbaz" is a little too big while
"boo" and "blah" are a little to small.


Any ideas? Thanks.


--
Alec S.
news/alec->synetech/cjb/net

Incorrect_Size.PNG

David Lowndes

unread,
Dec 17, 2008, 6:57:33 PM12/17/08
to
>I'm trying to set the widths of the headers in my list control myself since
>LVSCW_AUTOSIZE_USEHEADER has "special features" that I don't like.
>
>Some end up a little too big, and others a little too small. Here's the basic
>code I'm using in the list control:
>
> CString str = GetColumnName(this, nCol); // Retrieve header text
> CDC* dc = m_Header.GetDC(); // Get a DC from the header
> CSize size = dc->GetTextExtent(str); // Calculate text width
> int width = size.cx; // Store width of text string
> SetColumnWidth(nCol, width); // Set column width
>...

I'd try getting the font that the header control is using (by using
GetFont) and select that into the DC before using GetTextExtent.

Dave

Joseph M. Newcomer

unread,
Dec 17, 2008, 8:22:01 PM12/17/08
to
See below...

On Wed, 17 Dec 2008 17:48:36 -0500, "Alec S." <nos...@127.0.0.1> wrote:

>Blerg, I've got another problem.
>
>I'm trying to set the widths of the headers in my list control myself since
>LVSCW_AUTOSIZE_USEHEADER has "special features" that I don't like.
>
>Some end up a little too big, and others a little too small. Here's the basic
>code I'm using in the list control:
>
> CString str = GetColumnName(this, nCol); // Retrieve header text
> CDC* dc = m_Header.GetDC(); // Get a DC from the header

****
Why would you call GetDC() at all?
CClientDC dc(m_Header);
does what you need with no effort.

Don't forget to select the font into the DC:
CFont * f = m_Header.GetFont();
dc.SelectObject(f);
****


> CSize size = dc->GetTextExtent(str); // Calculate text width
> int width = size.cx; // Store width of text string
> SetColumnWidth(nCol, width); // Set column width

****
One of the serious problems about many controls is that they require a certain amount of
padding, COMPLETELY UNDOCUMENTED! For example, I have to add 12 to the width returned by
GetTextExtent.

Note that you can write
int width = dc.GetTextExtent(str).cx + 12;
and don't need to introduce the gratuitous size variable.
****


>
>I thought that maybe it's because GetTextExtent returns logical units, so I
>tried LPtoDP, but that did not change the numbers. GetOutputTextExtent gives the
>same numbers as GetTextExtent. I also tried DrawText(., DT_CALCRECT), but that
>gave the same-incorrect-numbers as well.

****
These tell you the width of the text. They give the correct width of the text. What you
neglected is that the width of the CONTROL is not the width of the TEXT but the width of
the text plus borders, edges. etc. It would be really nice if Microsoft documented this,
but that seems to be one of the concepts they don't understand. There should be a message
HDM_GETREQUIREDPADDING that returns the amount you should add, but that would involve
concepts like "design".
joe
****


>
>
>As you can see in the attached screencap, "foobarbaz" is a little too big while
>"boo" and "blah" are a little to small.
>
>
>Any ideas? Thanks.

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Alec S.

unread,
Dec 17, 2008, 8:25:31 PM12/17/08
to
"David Lowndes" <Dav...@example.invalid> wrote in message

> >
> >I'm trying to set the widths of the headers in my list control myself since
> >LVSCW_AUTOSIZE_USEHEADER has "special features" that I don't like.
> >
> >Some end up a little too big, and others a little too small. Here's the basic
> >code I'm using in the list control:
>
> I'd try getting the font that the header control is using (by using
> GetFont) and select that into the DC before using GetTextExtent.


That was suggested in a couple of the few pages I found that discussed
GetTextExtent returning the wrong size. I initially skipped that because it
seems redundant since I am getting a DC from the header control, so it should
already have the correct font and other attributes.

I tried it anyway, but not surprisingly it gave the same results:

CDC* dc = m_Header.GetDC();
CFont* font = dc->GetCurrentFont();
dc->SelectObject(font); // Seems redundant no?
CSize size = dc->GetOutputTextExtent(str); // Same wrong size

I even tried using a loop to cycle through the characters in the string,
accumulating their widths with GetOutputCharWidth, but that also gave the exact
same width as all of the others.

Alec S.

unread,
Dec 17, 2008, 8:45:16 PM12/17/08
to
"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:u29jk4pivdi1aik4s...@4ax.com...

> On Wed, 17 Dec 2008 17:48:36 -0500, "Alec S." <nos...@127.0.0.1> wrote:
>
> > CString str = GetColumnName(this, nCol); // Retrieve header text
> > CDC* dc = m_Header.GetDC(); // Get a DC from the header
>
> Why would you call GetDC() at all?
> CClientDC dc(m_Header);
> does what you need with no effort.
>
> Don't forget to select the font into the DC:
>
> One of the serious problems about many controls is that they require a certain
amount of
> padding, COMPLETELY UNDOCUMENTED! For example, I have to add 12 to the width
returned by
> GetTextExtent.


And there it is. Using CClientDC returns different widths than all of the others
that I tried. Of course it’s still to small, but that’s because of your second
point. Actually, I had already tried accounting for the borders and such (thanks
to experience with CSS) but that had not worked because the “fudge factor”
varied from column to column. This way however, adding a constant (12 worked
just fine) made them all fit correctly the same.

Hmmm, I’ll have to look into the difference. I figured that getting a DC from a
control was the logical thing to do.


Thanks a lot Joe.

Now I need to figure out how to do the same for the data strings in two
different scenarios (widest visible list string, and widest string in entire
list).

AliR (VC++ MVP)

unread,
Dec 18, 2008, 11:32:52 AM12/18/08
to
See if this helps:
http://www.codeproject.com/KB/combobox/Auto_Size_ListCtrl_Header.aspx

AliR.


"Alec S." <nos...@127.0.0.1> wrote in message
news:uLGcNnJY...@TK2MSFTNGP02.phx.gbl...

0 new messages