有什么方法可以检索 CEditBox 中文本的文本高度(以像素为单位)?

问题描述 投票:0回答:2

我有一个包含文本的编辑框,有时很长的句子。编辑框位于其父对话框的底部(如果我说错了,请原谅我,当涉及到 MFC 应用程序时,我不太知道自己在做什么)。当包含我的编辑框的对话框被绘制到屏幕上时,它没有被绘制得足够高,并且它在底部切断了我的编辑框的一部分。我希望能够计算编辑框中使用的文本的高度,并将该值的几个倍数添加到确定父对话框高度的函数中,以保持一致性。

我不确定这是否有意义,但最终我只是想找出是否可以在编辑框中获取文本的文本高度。鉴于编辑框是在项目中完全不同的文件中创建的,我不确定我的修复是否可能,但我认为这可能值得一问。

c++ mfc
2个回答
1
投票

您可以使用以下基本公式计算所需的文本高度:

CEdit::GetLineCount() * TEXTMETRIC::tmHeight

如果编辑控件具有任何

WS_BORDER
WS_HSCROLL
样式,则必须考虑窗口大小和内容大小之间的差距,该差距可以通过
CEdit::GetWindowRect()
返回的矩形高度之间的差来计算和
CEdit::GetRect()
(感谢巴马克!)。

以下是计算编辑控件“理想”大小的函数。返回的高度是适合内容所需的窗口高度。返回的宽度等于原始窗口宽度。您可以使用参数

minLines
maxLines
来确保返回的高度使得编辑控件在不滚动的情况下显示至少
minLines
和最大
maxLines
行数。将它们保留为默认值,以免限制高度。

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 {};
}

在编辑控件的父窗口的成员函数中像这样使用它来调整编辑控件的大小以适合其内容:

CSize const idealSize = GetEditIdealSize( m_edit );
m_edit.SetWindowPos( nullptr, 0, 0, idealSize.cx, idealSize.cy, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );

此代码已在 Windows 10 下针对样式为

ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_BORDER | WS_VISIBLE | WS_CHILD
的编辑控件进行了测试。


0
投票
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;
        }
    }
}

return sizeContent;
© www.soinside.com 2019 - 2024. All rights reserved.