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

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

在运行时,文本的第一个string是dynamic更新的。 此外,该文本string的字体将被replace为比它下面的IDC_STATIC_SECONDARYstring更大。 生成的文本string可能跨越一行,两行或更多。

我希望其他的静态控件在运行的时候将第二文本保存在标题string的正下方。 但是,我在WM_INITDIALOGcallback中重新定位这个控件的结果是不能很好地工作。 第二个string与第一个string重叠。 我想我可以使用DrawText和DT_CALCRECT来计算主文本string的高度,然后根据结果移动辅助文本string。 我的代码在这里看起来有些短暂:

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

这里是相关的ATL代码。 CMainWindow类只是inheritanceATL的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; } 

我究竟做错了什么?

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

这个设备上下文,尽管与窗口有关,但是加载了默认的参数,包括默认的字体(IIRC是从16位日子(这个屏幕截图的大部分)是旧的“系统”字体 )。

所以你需要做的是:

  1. 调用wndTitle.GetDC()来获得HDC
  2. 调用SelectObject()以选择正确的窗口字体(您可以使用WM_GETFONT来获取此;不知道MFC是否有一个包装函数),保存返回值,以前的字体,为步骤4
  3. 调用DrawText()
  4. 调用SelectObject()来选择返回的前一个字体
  5. 调用wndTitle.ReleaseDC()来声明你已经完成了使用HDC

更多详细信息在CWindow :: GetDC()的MSDN页面上 。