我想知道是否有一种简单的方法来计算字符串的文本范围(类似于GetTextExtentPoint32),但允许我指定要在计算中使用的 DPI。换句话说,是否有一个函数可以完全完成GetTextExtentPoint32的工作,但允许我将 DPI 作为参数传递,或者是一种“欺骗” GetTextExtentPoint32使用我可以指定的 DPI 的方法?
在你问“你到底为什么要这样做?”之前,我会尝试解释一下,但请耐心等待,这个请求背后的原因有些牵涉。
最终,这是一个自定义的自动换行算法,它将长字符串分解成更小的文本块,这些文本块需要整齐地适合具有复杂文本布局要求的 Crystal Report(它模仿警察用来提交刑事投诉的纸质表格,所以国家负责布局,而不是我们,它必须几乎完全匹配纸质表格)。
如果没有帮助,Crystal Reports 不可能正确布置此文本(文本必须适合一页上的一个小框,如果文本溢出小块,则后面是“标准大小”的续页),所以我编写了代码将文本分成多个“块”,这些“块”存储在报告数据库中,然后由报告单独呈现。
给定所需的尺寸(以逻辑英寸为单位)和字体信息,代码首先通过插入换行符使文本适合所需的宽度,然后根据文本高度将其分成正确大小的块。该算法使用 VB6 的TextHeight和TextWidth函数来计算范围,这将返回与GetTextExtentPoint32函数相同的结果(我检查过)。
当显示设置为 96dpi 时,此代码效果很好,但在 120 DPI 时会中断:有些行最终会包含更多的单词,而它们在 96 DPI 时会出现。
例如,“The quick brown fox jumps over the lazy dog”可能会中断如下:
96 DPI
敏捷的棕狐跳过
懒狗
120 DPI
敏捷的棕狐跳过
懒狗
此文本随后被 Crystal Reports 进一步分解,因为第一行不再适合报表上的相应文本字段,因此实际报表输出如下所示:
敏捷的棕狐跳过
懒狗
起初,我认为我可以通过将TextHeight和TextWidth的结果缩小 25% 来弥补这一点,但显然生活并不那么简单:似乎有许多舍入错误(可能还有其他因素?),所以与 96 DPI 相比,任何给定字符串的文本范围在 120 DPI 下永远不会大25%。我没想到它可以完美缩放,但有时甚至没有接近(在一项测试中,120 DPI 的宽度仅比 96 DPI 的宽度大 18% 左右)。
这不会发生在由 Crystal Report 直接处理的报表上的任何文本上:它似乎在缩放所有内容方面做得很好,因此报表在 96 DPI 和 120 DPI(甚至 144 DPI)。即使在打印报告时,文本也会完全按照屏幕上显示的方式打印(即看起来确实是所见即所得)。
鉴于所有这些,因为我知道我的代码在 96 DPI 下工作,我应该能够通过以 96 DPI 计算所有文本范围来解决问题,即使 Windows 当前使用不同的 DPI 设置。
换句话说,我希望我的FitTextToRect函数的结果在任何 DPI 设置下都返回相同的输出,方法是强制使用 96 DPI 计算文本范围。这一切都应该解决,因为我将范围转换回英寸,然后将它们与所需的宽度和高度(以英寸为单位)进行比较。我认为在像素和英寸之间来回转换时,96 DPI 产生的结果比 120 DPI 更准确。
我一直在研究 Windows字体和文本函数,看看是否可以滚动我自己的函数来计算给定 DPI 下的文本范围,查看GetTextMetrics和其他函数,看看这可能是多么容易或困难。如果有更简单的方法来实现这一点,在我开始创建自己的现有 Windows API 函数版本之前,我很想知道!