【问题标题】:What is the correct way to autosize a Static control?自动调整静态控件大小的正确方法是什么?
【发布时间】:2012-07-20 22:23:15
【问题描述】:

我想将静态控件的大小调整为其内容大小,因此我需要先计算其文本内容的大小。我找到了一种使用GetTextExtentPoint32 计算大小的方法,但是我需要先将DC 的字体设置为与控件的字体相同。有一个更好的方法吗?我已经设置了一次静态控件的字体,我想也许我不需要再设置 DC 的字体了。

计算静态控件文本内容大小的最佳方法是什么?有没有更好的方法来自动调整静态控件的大小?

【问题讨论】:

  • 给路过的人的提示:如果您正在使用 SysLink 控件,则会有一条消息,LM_GETIDEALSIZE

标签: winapi user-interface controls


【解决方案1】:

在我看来,您已经找到了正确的方法。调用GetTextExtentPoint32 以根据控件包含的文本确定控件的理想大小,然后将控件调整为计算出的大小。

工作量很大,但是当您使用原始 Win32 API 时就会发生这种情况。您没有一个方便的包装库,可以在 Control.AutoSize() 函数中为您抽象出所有这些内容。您可以轻松编写自己的函数并重新使用它,但 Win32 标准控件不公开“自动调整大小”API。

就字体而言,您肯定需要确保设备上下文使用与控件相同的字体,否则您将计算错误的大小。但是您不必创建新的设备上下文、请求处理静态控件的字体并将其选择到新的 DC 中。相反,您可以使用静态控件的 DC,使用 GetDC 函数并将句柄传递给静态控件窗口。确保如果您致电GetDC,您始终会在完成后致电ReleaseDC

但是,请注意GetTextExtentPoint32 函数的一些注意事项,这些注意事项可能会影响您计算大小的准确性:

  • 它忽略剪辑。
  • 计算高度时不考虑换行 (\n) 或回车 (\r\n)。
  • 它不考虑前缀字符(在字符串中以 & 号开头的字符),如果您的静态控件没有 SS_NOPREFIX style,则用于表示键盘助记符。
  • 考虑到某些设备可能会自动实现字距调整,它可能无法返回准确的结果。

(这在链接的文档中都提到了,但真的有人读过吗?)

也许一个更简单的选择是用静态控件已经在做的同样的方式来绘制文本。除非你有 SS_SIMPLE 样式集(它使用 TextOutExtTextOut 来绘制文本作为优化),静态控件通过调用带有适当参数的 DrawText 函数来绘制它们的文本,给定其他控件样式已设置 (reference)。

你可以做同样的事情,并在你的调用中添加 DT_CALCRECT 标志到 DrawText 函数,这会导致它确定绘制指定文本所需的矩形的宽度和高度 实际绘制文本。

【讨论】:

  • 似乎GetTextExtentPoint32 没有“忽略”字距,相反,它计算字距到总大小。但是对于单个字符,字距不会被计算在内,所以“字符串中字符的范围之和并不总是等于字符串的范围。”
  • 很公平,它不会忽略字距调整,只是由于字距调整存在差异,它可能无法报告准确的结果。我会解决的。
  • 我认为当设备紧缩字符时,GetTextExtentPoint32 是准确的,因为它也计算字距。
【解决方案2】:

据我所知,静态控制没有自动调整大小。你做得对。

  1. 使用GetWinDowText获取静态窗口的文本
  2. 使用 GetDC 获取窗口的 dc
  3. 使用 WM_GETFONT 获取窗口的字体并将字体选择到 dc 中
  4. 使用其中一种文字大小计算功能来计算文字大小
  5. 恢复原来的dc字体
  6. 发布直流

您将始终必须在 dc 中选择正确的字体才能获得准确的结果。此外,我个人更喜欢使用 DT_CALCRECT 的 DrawText 来计算文本的大小。参考http://msdn.microsoft.com/en-us/library/windows/desktop/dd162498%28v=vs.85%29.aspx

使用 DrawText,如果文本以 NULL 结尾,您不必提供字符数。另外,您可以结合各种格式选项来调整计算。例如,静态控件文本中的 & 字符为下一个字符加下划线。使用 Drawtext,您将能够正确计算大小,但在 GetTextExtentPoint32 中没有规定指定这一点。

【讨论】:

    【解决方案3】:

    大多数使用静态文本控件的窗口都是对话框,其中静态控件的大小以对话框单元 (DLU) 表示,它大致解释了字体的大小。通过这种方式,对话框控件往往具有合理的大小。

    如果您不使用对话框,您可以尝试使用MapDialogRect 伪造对话框行为。

    否则你必须使用GetTextExtentPoint32

    【讨论】:

    • 天哪,不。你永远不想使用GetDialogBaseUnits,因为它只为使用“默认系统字体”(SYSTEM_FONT)的对话框返回对话框基本单位。自 Windows 3 时代以来,Windows 应用程序就没有使用过。正如您链接到的文档所说,您需要调用 MapDialogRect。有关GetDialogBaseUnits 问题的更多信息,请参阅Raymond Chen's blog post on the subject
    • 啊,谢谢;自从我处理对话单元以来已经很长时间了......我会编辑。
    • Raymond Chen 关于 GetDialogBaseUnits 的博文has moved
    猜你喜欢
    • 2016-11-19
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多