如何计算静态控件中文本的实际高度

时间:2015-02-14 13:33:22

标签: windows winapi

我的简单Win32 DialogBox包含两个静态文本控件(IDC_STATIC_TITLE和IDC_STATIC_SECONDARY),这里是它在资源编辑器中的样子:

在运行时,文本第一个字符串会动态更新。此外,替换该文本字符串的字体,使其大于它下面的IDC_STATIC_SECONDARY字符串。生成的文本字符串可能跨越一行,两行或更多行。

我希望保持辅助文本的其他静态控件在运行时直接放在标题字符串下面。但是,我在WM_INITDIALOG回调中重新定位此控件的尝试并不能很好地工作。第二个字符串与第一个字符串重叠。我以为我可以使用带有DT_CALCRECT的DrawText来计算主文本字符串的高度,然后根据结果移动辅助文本字符串。我的代码有点短,如下所示:

DrawText返回一个坐标为{top=42 bottom=74 left=19 right=461}的RECT。从顶部减去底部是" 32"。这看起来有点短。我怀疑我没有正确调用API和/或逻辑和像素单元之间的不同映射存在问题。

这是相关的ATL代码。 CMainWindow类仅继承自ATL的CDialogImpl类。

CMainWindow::CMainWindow():
_titleFont(NULL),
_secondaryFont(NULL)
{
    LOGFONT logfont = {};
    logfont.lfHeight = 30;
    _titleFont = CreateFontIndirect(&logfont);
}

LRESULT CMainWindow::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    CString strTitle;
    RECT rectDrawText = {}, rectTitle={}, rectSecondary={};
    CWindow wndTitle = GetDlgItem(IDC_STATIC_TITLE);
    CWindow wndSecondary = GetDlgItem(IDC_STATIC_SECONDARY);

    this->GetDlgItemText(IDC_STATIC_TITLE, strTitle);

    wndTitle.SetFont(_titleFont);   // font created with Create

    wndTitle.GetWindowRect(&rectTitle);
    wndSecondary.GetWindowRect(&rectSecondary);
    ScreenToClient(&rectTitle);
    ScreenToClient(&rectSecondary);

    rectDrawText = rectTitle;
    DrawText(wndTitle.GetDC(), strTitle, strTitle.GetLength(), &rectDrawText, DT_CALCRECT|DT_WORDBREAK); // compute the actual size of the text

    UINT height = rectSecondary.bottom - rectSecondary.top;  // get the original height of the secondary text control
    rectSecondary.top = rectDrawText.bottom;                 // position it to be directly below the bottom of the title control
    rectSecondary.bottom = rectSecondary.top + height;       // add the height back
    wndSecondary.MoveWindow(&rectSecondary);

    return 0;
}

我做错了什么?

1 个答案:

答案 0 :(得分:2)

尽管它的名字可能听起来像,wndTitle.GetDC()不返回某些指针/引用,它是CWindow的一部分,并且每个调用都是相同的。相反,它每次都会为窗口检索一个全新的设备上下文。 (它基本上是GetDC() Windows API调用的瘦包装,直到返回HDC而不是MFC等效。)

此设备上下文尽管与窗口关联,但仍加载了默认参数,包括默认字体(IIRC为that old "System" font from the 16-bit days (most of this screenshot))。

所以你需要做的是:

  1. 致电wndTitle.GetDC()以获取HDC
  2. 调用SelectObject()以选择正确的窗口字体(您可以使用WM_GETFONT来获取此字体;不确定MFC是否具有包装函数),保存返回值,以前的字体,第4步
  3. 致电DrawText()
  4. 致电SelectObject()select the previous font back in
  5. 致电wndTitle.ReleaseDC(),说明您已完成使用HDC
  6. 更多详情请见the MSDN page for CWindow::GetDC()