Jump to content
Tuts 4 You

cPaintDC.GetTextExtent LineHeight computation very bogus: alternatives???


CodeExplorer

Recommended Posts

CodeExplorer
Posted

cPaintDC.GetTextExtent LineHeight computation very bogus: alternatives???

LOGFONT lf;
    memset(&lf, 0, sizeof(lf));
    HGDIOBJ hFont = ::GetStockObject(OEM_FIXED_FONT);
    ::GetObject(hFont, sizeof(lf), &lf);

    lf.lfHeight = 100;
    lf.lfPitchAndFamily = FIXED_PITCH;

    CFont font;
    font.CreatePointFontIndirect(&lf);

    pOldFont = cMemDC.SelectObject(&font);

    // Get size information
    int cWidth;
    cPaintDC.GetCharWidth('0', '0', &cWidth);
    CSize cSize = cPaintDC.GetTextExtent("0", 1);
    int nLineHeight = cSize.cy;

    ySizeChar = nLineHeight;
    xSizeChar = cWidth;


    // memorybuffered output (via a memorybitmap)
    cMemDC.CreateCompatibleDC(&cPaintDC);
    GetClientRect(cClientRect);
    xClient = cClientRect.Width();
    yClient = cClientRect.Height();

    int maxPLen = yClient/ySizeChar;  // 10

    if (yClientMax>yClient)
    {
    EnableScrollBar(SB_VERT);
    ShowScrollBar(SB_VERT, true);
    }

maxPLen is 10 so maxim 10 lines, I've entered 13 and there is still space on my editbox,
my only thoughts is that cPaintDC.GetTextExtent("0", 1); cSize.cy computation is wrong,
any alternative to it?

 

CodeExplorer
Posted

There was a bug with my code: cPaintDC should have been instead cMemDC: the CDC for which we previously set the font.
The second thing: those are called from OnPaint method, first time yClient = cClientRect.Height() will get a wrong bigger value, second time it will return the good value.
 

CodeExplorer
Posted

Just another way to compute size of text, will return same size as previous one:

https://github.com/cmacro/simple/blob/master/gdi_win/testscrollcalc/scrolltest.cpp
inside LRESULT CALLBACK MyTextWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    // Extract font dimensions from the text metrics
    TEXTMETRIC tm;
    GetTextMetrics(cMemDC, &tm);
    int xChar = tm.tmAveCharWidth;
    int xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar / 2;
    int yChar = tm.tmHeight + tm.tmExternalLeading;

The error seems to be of "2 chars" in my computations, don't know if is normal!
 

CodeExplorer
Posted

Kurapica: thank you for your help.

An example:
    SIZE textSize;
    GetTextExtentPoint32A(cMemDC, "0", 1, &textSize);

returns same size as all including the above GetTextMetrics.

All those things needed for implementing hex view editbox.
Normal editbox won't show properly hex chars (same size).
Maybe somebody know an easy way to fix editbox...
 

 

Posted

Why not use a Monospaced font so they will all be fixed-width

Posted (edited)

Any of them in that list are fixed-width so choose anything that suits

Courier is one I use if I want a fixed-width font

Edited by NOP
CodeExplorer
Posted

I forget to specify something: I am on Visual C++ 6.0
on C# I did it like this:
        textBox1.Font = new Font(FontFamily.GenericMonospace, textBox1.Font.Size);
        textBox1.Text = "44 43 5F 43 4F 4D 50 41\r\n4E 46 52 41 4D 45 0D 0A";

and it works perfectly,
https://stackoverflow.com/questions/7285166/c-sharp-net-multiline-textbox-with-same-width-characters
it given me some idea of something like getting all fonts measure their size and create a list.
 

  • Like 1
CodeExplorer
Posted

The font list is not interesting at all, beside Courier there is also Terminal font.
So I am once again stacked, strange enough to see that on C# all works ok.
 

Posted

My C++ isn't great but have you tried sending WM_SETFONT to the edit control?

SendMessage(hEdit, WM_SETFONT, (WPARAM)hFont, TRUE)

 

CodeExplorer
Posted

I found the error inside my code:
font.CreatePointFontIndirect(&lf);
should be instead:
    HFONT hFontNew = CreateFontIndirect(&lf);
    ::SendMessage(handle3, WM_SETFONT, (WPARAM)hFontNew, TRUE);

Complete code:

    LOGFONT lf;
    memset(&lf, 0, sizeof(lf));
    HGDIOBJ hFont = ::GetStockObject(OEM_FIXED_FONT);
    ::GetObject(hFont, sizeof(lf), &lf);

    lf.lfHeight = 12;
    _tcscpy(lf.lfFaceName, _T("Terminal"));  // Monospace
    lf.lfPitchAndFamily = FIXED_PITCH;

    HFONT hFontNew = CreateFontIndirect(&lf);
    ::SendMessage(handle3, WM_SETFONT, (WPARAM)hFontNew, TRUE);

Now all works ok.
 

  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...