2

I would like to determine real font line height based on font taken from system. The font I use is system icon font.

Here is my code so far.

LOGFONTW lf;
ZeroMemory(&lf, sizeof(lf));
// Get icon font size from the system    
if (SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
    {
    int H = 7;
        {
        // Create TBitmap and TFont
        boost::scoped_ptr<Graphics::TBitmap> bmp(new Graphics::TBitmap);
        boost::scoped_ptr<TFont> fnt(new TFont);

        // Assign font from the system
        fnt->Name   = lf.lfFaceName;
        fnt->Height = lf.lfHeight;
        bmp->Canvas->Font->Assign(fnt.get());

        // Calc height (returns 13 for default font size, 96 DPI but should be more like 18)
        H = bmp->Canvas->TextHeight("Wq");
        }

    VST->DefaultNodeHeight = H;
    VST->Font->Name        = lf.lfFaceName;
    VST->Font->Height      = lf.lfHeight;
    }

Now here is the problem. The above calculates text height which is 13 pixels for default font size at 96 DPI. But it should be 18 actually for nice pitch and line spacing. The difference increases as DPI is enlarged or font size is enlarged. If VirtualTreeView DefaultNoteHeight is set to 13 pixels it all looks very tight and lines are too close to each other.

What I need to know is actually line spacing as explained here: http://msdn.microsoft.com/en-us/library/xwf9s90b%28v=VS.71%29.aspx

Please explain how do I extract line spacing from the given font from the system.

I believe GetTextMetrics holds the key but I just miss small piece of the puzzle to put it all together how to use it together with the above.

Examples in Delphi also welcome doesn't have to be in C++ Builder.

Update:

I've revised the formula a bit by adding:

H = bmp->Canvas->TextHeight("Wq");
// Take care of smaller heights to make them minimum 18 pixels
H = (H < 18)? 18 : H;

Seems to work OK for all font sizes I've tested with (for larger fonts it is a bit more tight but that's OK).

Coder12345
  • 3,431
  • 3
  • 33
  • 73
  • I guess you don't want to use GDI+, or...? (asking because methods used in that MSDN article can be quite easily extracted, like e.g. [`GetLineSpacing`](http://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Advanced/FontFamily.cs#518), but they are GDI+). – TLama Oct 16 '14 at 12:59
  • I just need to measure line spacing, if it is compatible with Windows XP or later then I'm good with it. – Coder12345 Oct 16 '14 at 14:45
  • If you want the actual height of the Font you can try http://stackoverflow.com/questions/6804929/how-do-i-determine-the-height-of-a-line-of-text-in-a-tmemo-programmatically – fuchs777 Oct 16 '14 at 15:10

1 Answers1

1

I have used this code to calculate the rect needed to display a block of text, it might be of some use to you:

It's an adaptation from my original code, but it should give you the idea: DT_CALCRECT is the flag to set so it returns the rect needed.

RECT rc_ancho_en_gui;
int height = 0;

rc_ancho_en_gui.left = 0;
rc_ancho_en_gui.right = 100;
rc_ancho_en_gui.top = 0;
rc_ancho_en_gui.bottom = 100;

height = DrawText(BitmapHandle, "Wq", 2, &rc_ancho_en_gui, DT_CALCRECT | DT_WORDBREAK);

I used before TextHeight but it didn't work fine, either giving me more or less than what was really needed. This way I haven't had any issues with the resulting height.

Rodrigo Gómez
  • 1,079
  • 8
  • 24
  • I examined this and it seems this does give good values... I will examine it further a bit, this might be it! – Coder12345 Oct 16 '14 at 18:12
  • I was thinking that you might be able to pass some multiline text, say, `Wq\njÑ` and divide the result between the number of lines, and you will get the average line height. My problem with TextHeight was actually with multiline text, as the calculation it gave was always off. With this method the height corresponds correctly to what the user expects, but maybe passing a single char or two doesn't allow this to take into consideration the line spacing. – Rodrigo Gómez Oct 16 '14 at 18:18
  • After further testing I found out that `DrawText` and `TextHeight` return identical values. There is no need to divide with multiple lines, single line returns always same value even if you put in text `AA` or `Wq` it is always the same height. I've revised formula in my original post which seems to work OK. Even Windows Explorer crops fonts with large DPI on Windows 8.1 which is very odd and the above formula works better than Windows Explorer. – Coder12345 Oct 16 '14 at 21:52