cashiba 发表于 2016-4-15 19:19:33

一个困扰已久的问题:如何计算文本宽度?

在类似于table、grid、redit之类的控件中常常涉及到文本换行,大多可以用控件自身的wrap自动换行方法,但有时需要计算文本总宽度,然后让文本按指定宽度自动折行。因为涉及到字体、字符宽度、字符间距、屏幕分辨率等等元素,需要很懂API才行。小白如我常常对api望而生畏,不明觉厉。度娘之,多是C/C++、.net语言等之类的有所涉及,也是一头雾水。最近又想起这个问题,所以发此贴,希望路过的万能的ACN大神们顺手给破了吧{:face (316):}

记事本比较通用,就拿记事本来测试

如何达到下图效果:

这是样本:

haijie1223 发表于 2016-4-15 20:27:40

什么意思,让记事本自动换行?

cashiba 发表于 2016-4-15 21:58:58

本帖最后由 cashiba 于 2016-4-15 22:07 编辑

什么意思,让记事本自动换行?
haijie1223 发表于 2016-4-15 20:27 http://www.autoitx.com/images/common/back.gif不是记事本本身的自动换行,而是想实现 按若干个字符宽度的文本 来换行,最主要的就是如何获得单个字符宽度(包括英文字符、标点符号等)...不知道我的意思表述得清不清楚{:face (239):}
换个简单的说法,
假定记事本是最大化,宽度固定等于屏幕宽度。
以前呢,文本到记事本右边缘就自动换行;
现在呢,希望文本到记事本中间(也就是半屏幕宽度)时就自动换行
如何实现呢?

331358996 发表于 2016-4-15 22:09:16

哟嚯哦 这个厉害了 需要高手来帮忙了
呵呵 我等只能帮顶 顺便看看学习一下

haijie1223 发表于 2016-4-15 22:28:15

回复 3# cashiba


    答非所问的感觉,谁看懂楼主的意思了?楼主是要在记事本换行吗?还是在word换行?还是在dos下换行?还是要在美国换行?还是在日本换行?

cashiba 发表于 2016-4-15 22:44:26

本帖最后由 cashiba 于 2016-4-15 22:47 编辑

回复cashiba


    答非所问的感觉,谁看懂楼主的意思了?楼主是要在记事本换行吗?还是在word换行? ...
haijie1223 发表于 2016-4-15 22:28 http://www.autoitx.com/images/common/back.gif版主不用冷嘲热讽吧?
记事本换行,还是word换行,还是表格里换行....都可以,只是以记事本为例子罢了。就是想知道某分辨率下某种字体的字符怎么计算其字符宽度(不是占用的位宽或字节长度)而已。
或者给定的宽度能容纳下多少个字符。我觉得自己已经表述清楚了.....

haijie1223 发表于 2016-4-15 23:24:38

回复 6# cashiba


    既然认为我在冷嘲热讽,那就当我没回复过,帮你顶帖了。

chamlien 发表于 2016-4-16 10:44:54

提供一个思路。
首先获取得记事本的宽度A,宽度A/2就是换行的位置;
宽度A/2可以使用定时监控光标的在记事本里的坐标,横坐标>=A/2时换行。

以上思路仅适用记事本宽度一定时才有效。如果多行文本输入后,此时拉大或拉小记事本宽度,再实现换行,这种情况暂未有思路。

fuldho 发表于 2016-4-16 11:38:19

回复 6# cashiba

不同大小字体在不同分辨率下所容纳字符数是一个未知变量,

水木子 发表于 2016-4-16 11:51:53

#include <WinAPI.au3>
_WinAPI_GetTextExtentPoint32($hDC, $sText)

cashiba 发表于 2016-4-16 12:20:11

本帖最后由 cashiba 于 2016-4-16 12:28 编辑

提供一个思路。
首先获取得记事本的宽度A,宽度A/2就是换行的位置;
宽度A/2可以使用定时监控光标的在记事 ...
chamlien 发表于 2016-4-16 10:44 http://www.autoitx.com/images/common/back.gif这种方法也想到过,只是觉得通用性不强。以前曾经在网络上搜到一段代码,可惜再找不到了。好像有几个文本或字符串API函数组合在一起,能够根据当前字体、分辨率等自动计算出字符宽度和高度。记得其中有个 getFontMetrics 什么的。
AU3通过dllcall引用API的方法刚刚知道,一时还没熟悉,所以不知道在AU3里是怎么引用API来计算字符宽和高的。故有此一问。
之所以要计算字符宽或高,主要是因为,有时数千字的文本要分段输入一个文本框里,每段之前有个固定的标题或引子截断,需要按标题或引子定位输入。或者文字排版时也需要精确计算字符宽高。通常的记事本或word自动换行都是靠近边框时才触发换行,不像是按字符宽度来折行的。

cashiba 发表于 2016-4-16 12:34:11

本帖最后由 cashiba 于 2016-4-16 12:37 编辑

下面是网上搜到的一些
 如何获得一个字符的宽度和高度?
  
   可以利用FontMetrics对象所提供的getHeight(), charWidth()或者是stringWidth()
   方法来获得显示某个字符或者是字符串所需要的高度和宽度。例如,在Graphics g中:
  
   String Info = "Test String".
   FontMetrics metrics = getFontMetrics(g.getFont());
   int height = metrics.getHeight();
   int width = metrics.stringWidth(Info);
  
   关于这些方法的具体情况,请参考FontMetrics类的API文档。
另一个,flash脚本中
经过自己的一番研究,可以从flex的as3帮助文档中找到答案,flash.text.TextLineMetrics类负责测量字符串所占的实际宽度。   

有关详细信息请自己参考API.
measureText(字符串)方法返回TextLineMetrics的实例,TextLineMetrics类的width返回字符串所占的实际宽度,Flex的显示组件一般都继承自UIComponent组件,UIComponent类含有measureText方法,因此可以直接使用this.measureText(字符串).
引自:http://yunzhongxia.iteye.com/blog/856982

cashiba 发表于 2016-4-16 12:48:43


水木子 发表于 2016-4-16 11:51 http://www.autoitx.com/images/common/back.gif谢谢水版!原来AU3里已经有这样的自定义函数了
_WinAPI_GetTextExtentPoint32 (设备环境标识,文本字符串)Func GetStringDimensions($hWnd, $sText)
    Local $hDC = _WinAPI_GetDC($hWnd) ; 获取当前窗口的设备环境句柄.
    Local $hFont = _SendMessage($hWnd, $WM_GETFONT) ; 检索控件目前正在绘制文本的字体.
    Local $hSelectObject = _WinAPI_SelectObject($hDC, $hFont) ; 选择设备环境对象.
    Local $tSIZE = _WinAPI_GetTextExtentPoint32($hDC, $sText) ; 检索字符串的高度和宽度.

    _WinAPI_SelectObject($hDC, $hSelectObject)
    _WinAPI_ReleaseDC($hWnd, $hDC) ; 释放设备环境.
    Local $aReturn = ; 设置字符串宽度和高度的数组.
    Return $aReturn
EndFunc   ;==>GetStringDimensions不懂API的看起来很高大上似的,怎么用还得好好学学....以前用的那个VB还是啥语言写的函数忘了,代码比较多,但是用起来很不错,估计原理都是一样的.....
再次感谢{:face (316):}

cashiba 发表于 2016-4-16 12:55:05

回复cashiba
不同大小字体在不同分辨率下所容纳字符数是一个未知变量,
fuldho 发表于 2016-4-16 11:38 http://www.autoitx.com/images/common/back.gif所以希望有一个通用性比较强的函数,只要给定一段文本,就能根据当前编辑控件宽度计算出该文本可以折多少行,然后就可以任意按行数分段截取文本,而不用考虑分辨率、字体、中西文、标点符号之类的具体设定。

cashiba 发表于 2016-4-16 13:00:58

学会用这个自定义函数后,再向大家汇报心得,感谢各位大侠和大神路过并驻足提点!{:face (332):}
页: [1] 2
查看完整版本: 一个困扰已久的问题:如何计算文本宽度?