Reputation: 43
I have an edit box that contains text, sometimes many sentences long. The edit box sits at the bottom of its parent dialog (forgive me if I'm saying everything wrong, I don't quite know what I'm doing when it comes to MFC applications). When the dialog that contains my edit box in mind is drawn to the screen, it isn't drawn quite tall enough, and it cuts off a portion of my edit box at the bottom. I was hoping to be able to calculate the height of the text that is used in the edit box, and add a few multiples of that value to the function that determines the height of the parent dialog, for consistency.
I'm not sure if this makes sense, but ultimately I am just trying to find out if it's possible to get text height of text within my edit box. I'm not sure that my fix is even possible given that the edit box is created in a completely different file in the project, but I thought it might be worth asking.
Upvotes: 2
Views: 1285
Reputation: 1
CSize sizeContent(0, 0);
int nCharCount = GetWindowTextLength();
if (0 < nCount)
{
// Set the width of content to that of text area of your CEdit
GetRect(rect);
sizeContent.cx = rect.Width();
// otherwise, you can compute the maximum pixel width of text lines
// by iterating each line of text;
// for each line of text
// get the indices of the first and the last character of the line
// with those indices, get pixel position of chars at both ends
// to get the pixel width of each line
// update the maximum pixel width of a text line, if needed
// <Note> you can use CEdit's members
// int LineIndex(iLine);
// returns the zero based index of the first character of 'iLine',
// which is the very next index of the prevous line's last
// character as well. 'iLine' is also zero-based one.
// CPoint PosFromChar(iChar);
// returns the pixel position of (zero-based index) iChar
// <Note> to get the enough pixel width of the maximum line,
// you need to plus to each line the pixel width of maximum
// character width that you can get with;
// TEXTMETRIC tm;
// dc.GetTextMetrics(&tm);
// And then, get the pixel height of a single line
// using the last two valid lines of text
int iFirstLine = GetFirstVisibleLine();
int nLineCount = GetLineCount();
ASSERT(iFirstLine < nLineCount); // even with null content
if (1 < nLineCount) // GetLineCount() returns 1
{
CPoint pos2 = PosFromChar(nCount - 1);
CPoint pos1 = PosFromChar(LineIndex(LineFromChar(nCount - 1) - 1));
if (0 < pos1.y && pos1.y < pos2.y)
{
sizeContent.cy = (pos2.y - pos1.y) * (nLineCount - iFirstLine);
}
}
}
return sizeContent;
If you want to get the size of the whole text,
instead of the visible portion of text only,
you can set iFirstLine to zero.
Upvotes: 0
Reputation: 27766
You could calculate the required text height using this basic formula:
CEdit::GetLineCount() * TEXTMETRIC::tmHeight
If the edit control has any of WS_BORDER
or WS_HSCROLL
styles you have to account for the gap between window size and content size which can be calculated by taking the difference between the heights of the rectangles returned by CEdit::GetWindowRect()
and CEdit::GetRect()
(thanks Barmak!).
The following is a function to calculate the "ideal" size of an edit control. The returned height is the required window height to fit the content. The returned width equals the original window width. You can use the parameters minLines
and maxLines
to make sure the returned height is such that the edit control shows at least minLines
and at maximum maxLines
number of lines without scrolling. Leave them at their defaults to not restrict the height.
CSize GetEditIdealSize( CEdit& edit, unsigned minLines = 0, unsigned maxLines = 0 )
{
if( CFont* pFont = edit.GetFont() )
{
// Get font information.
CClientDC dc( &edit );
auto const pOldFont = dc.SelectObject( pFont );
TEXTMETRICW tm{}; dc.GetTextMetricsW( &tm );
if( pOldFont )
dc.SelectObject( pOldFont );
// Calculate required height for the text content.
int const heightRequired = edit.GetLineCount() * tm.tmHeight;
// Make sure the edit control height stays between the given minimum/maximum.
int idealHeight = std::max<int>( heightRequired, tm.tmHeight * minLines );
if( maxLines > 0 )
idealHeight = std::min<int>( idealHeight, tm.tmHeight * maxLines );
// Get window and content rect.
CRect rcEdit; edit.GetWindowRect( rcEdit );
CRect rcContent; edit.GetRect( rcContent );
// Account for gap between window rect and content rect.
idealHeight += rcEdit.Height() - rcContent.Height();
return { rcEdit.Width(), idealHeight };
}
return {};
}
Use it like this in a member function of the parent window of the edit control to resize the edit control to fit its content:
CSize const idealSize = GetEditIdealSize( m_edit );
m_edit.SetWindowPos( nullptr, 0, 0, idealSize.cx, idealSize.cy, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
This code has been tested under Windows 10 for an edit control with the style ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_BORDER | WS_VISIBLE | WS_CHILD
.
Upvotes: 1